问题
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.
回答1:
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...)
{
// ...
};
回答2:
Your class is parameterized by the return value and types of arguments, spelled out separately. But when instantiating, you try to parameterize it by a function type, a la std::function
. Make it func<int, int, int> myfunc;
. With this change, your code works.
回答3:
You need partial specialization.
Here's a working example:
template <typename T>
class func;
template <typename R, typename... Tn>
class func<R(Tn...)> {
typedef R (*fptr_t)(Tn...);
fptr_t fptr;
public:
func() : fptr(nullptr) {}
func(fptr_t f) : fptr(f) {}
R operator()(Tn... args) {
return fptr(args...);
}
func& operator=(fptr_t f) {
fptr = f;
return *this;
}
};
来源:https://stackoverflow.com/questions/19695988/function-wrapper-via-function-object-class-variadic-template