Function wrapper via (function object) class (variadic) template

两盒软妹~` 提交于 2019-12-11 05:54:50

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!