C++
I'm trying to implement a function wrapper via a (function object) class (variadic) template. The class has as its only data member a function pointer that is initialized by or assigned the function pointer it is wrapping. The parametrized constructor takes a function pointer and initializes the member by it. The operator()
method takes argument(s) (or none) and calls the wrapped function with them. At least that's the idea. I get many errors, which I mark with comments. VC11 (with the November 2012 CTP, to enable variadic templates) gives me error C2091: function returns function
in all but one of the marked areas. The last error is different, and I comment its full description in the code. g++ gives mostly the same errors, albeit with different code numbers.
#include <iostream>
template <typename R, typename... Tn>
class func
{
R (*fptr)(Tn...); // C2091
public:
func() : fptr(nullptr) {}
func( R (*f) (Tn...) ) : fptr(f) {} // C2091
R operator()(Tn... args)
{ // C2091
return fptr(args...);
}
func& operator=( R (*f) (Tn...) ) // C2091
{
fptr = f;
return *this;
}
};
int foo(int a, int b)
{
std::cout << "foo\n";
return 0;
}
int main()
{
func<int(int, int)> myfunc;
myfunc = foo; // C2679: binary '=' : no operator found which takes
// a right-hand operand of type 'int (__cdecl *)(int,int)' (or
// there is no acceptable conversion)
}
Why am I getting these errors? For example, I don't see how the parametrized constructor returns anything, or how the declaration of the data member returns anything. Isn't the data member declaration in the form of a function pointer declaration? For example, doesn't int (*g)(int);
declare a pointer that points to a function that takes an int
and returns an int
?
Edit/Addendum:
I see from the answers that int(int, int)
is only one type and that I need partial specialization to get the effect I want. But, what produces the error in my code? If I comment out myfunc = foo
, I still get the other errors. func<int(int, int)> myfunc;
calls the default constructor. typename R
gets instantiated to int(int, int)
, and typename... Tn
becomes empty. The data member R (*fptr)(Tn...);
becomes R (*fptr)();
, and fptr
is therefore a function pointer that points to a function that takes zero arguments and returns an R
. If R
is int(int, int)
, then is R
a function pointer type or a function type? If it's the latter, then I can understand the context of the error message.
int(int, int)
is one single type. If you want to pass it like that and unwrap it, you need partial specialization:
template <typename> struct func; // leave undefined
template <typename R, typename ...Args>
struct func<R(Args...)> // specialized for typename = R(Args...)
{
// ...
};