2

Is there a way to rewrite the curry template class definition so main accepts curry<addtogether> instead of the current curry<int,int,int,addtogether>?

#include<iostream>

int addtogether(int x,int y){
    return(x+y);};

template<class T,class U,class V,T(*F)(U,V)>
class curry{
private:
    const U y;
public:
    curry(U x):y(x){};
    T operator()(V v){return(F(y,v));};
};

int main(){
    {using namespace std;
    cout<<curry<int,int,int,addtogether>(1)(1);}
};

This should be doable as addtogether is known at compile time. I've just not seen many templates with function pointers. The majority are of the form int(*f)(int,int) which is not polymorphic enough. I'm seeking a template definition that will accept any function pointer with two arguments.

Thanks!

Edit: If what I'm asking is indeed impossible, I thought of the following workaround:

#include<iostream>

class addtogether{
public:
    typedef int v1;
    typedef int v2;
    typedef int v0;
    int operator()(int x,int y){
    return(x+y);};
};

template<class F>
class curry{
public:
    typedef typename F::v2 v1;
    typedef typename F::v0 v0;
    const typename F::v1 y; 
    curry(const typename F::v1 x):y(x){};
    v0 operator()(const v1 v){return(F()(y,v));};
};

int main(){
{using namespace std;
    cout<<curry<addtogether>(1)(1);}
};

I could look into even replacing the type placeholders v0 v1 v2 by a list of types. Something I wanted to share anyway...

dumb0
  • 337
  • 1
  • 8
  • 3
    Not as the class (template non-type parameters whose types are deduced are relatively often requested). But you can use a function template instead, and either pass the function pointer as a run-time parameter (relying on compiler optimizations to remove that indirection) or wrap it in a lambda. – dyp Nov 21 '14 at 23:35
  • Related: http://stackoverflow.com/q/26655685 – dyp Nov 21 '14 at 23:36
  • Duplicate: http://stackoverflow.com/q/19857444 http://stackoverflow.com/q/14710842 http://stackoverflow.com/q/15983802 (and many more) – dyp Nov 21 '14 at 23:37
  • I can't believe this isn't possible! What corner case would prevent the compiler from inferring the type of function pointers at compile time? – dumb0 Nov 22 '14 at 00:27
  • It is not impossible, it just isn't supported for class templates. There are [proposals](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3601.html) to introduce a way to let the compiler deduce the type of a non-type template argument. – dyp Nov 22 '14 at 00:35
  • 1
    You can deduce the types `vX` from the signature of `operator()` if it isn't overloaded. Also, you don't *have* to deduce those types - all you need is to store the arguments, then pass them to some function (object). See the first link: [How to make curry?](http://stackoverflow.com/q/26655685) – dyp Nov 22 '14 at 00:37
  • @dyp, that proposal wasn't very popular and is unlikely to happen – Jonathan Wakely Nov 22 '14 at 01:59
  • @JonathanWakely I've heard some rumours; also, Stroustrup said in a hangout there's a more general problem in `std::array a = {1,2,3};` or even `std::array a = {1,2,3}`. People here on SO have repeatedly and independently "proposed" another syntax `template`, not sure if that has been proposed officially (or why the one I linked wasn't very popular). – dyp Nov 22 '14 at 17:22
  • @dyp I think the Concepts TS allows `curry` so the first three parameters would be deduced, and maybe even `curry`, which is more consistent with the existing syntax and semantics of function template argument deduction and generic lambdas. – Jonathan Wakely Nov 22 '14 at 18:08

1 Answers1

2

Is there a way to rewrite the curry template class definition so main accepts curry<addtogether> instead of the current curry<int,int,int,addtogether>?

No, because the non-type template parameter F depends on the earlier template parameters, so cannot be declared before them.

Do you really need the function pointer to be part of the type, rather than stored as a member variable of curry? Using a member variable would allow it to be deduced in a function template:

template<class T,class U,class V>
class curry{
private:
    T (*f)(U,V);
    const U y;
public:
    curry(T (*f)(U,V), U x): f(f), y(x){};
    T operator()(V v){return(f(y,v));};
};

template<class T,class U,class V>
curry<T, U, V>
make_curry(T (*f)(U,V), U u)
{
  return curry<T, U, V>(f, u);
}
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521