函数包装器通过(函数对象)类(可变参数)模板

时间:2013-10-30 23:51:00

标签: c++ function-pointers variadic-templates functor function-object

C ++

我正在尝试通过(函数对象)类(可变参数)模板实现函数包装器。该类具有作为其唯一数据成员的函数指针,该函数指针由其包装的函数指针初始化或分配。参数化构造函数接受函数指针并通过它初始化成员。 operator()方法接受参数(或无),并用它们调用包装函数。至少这是个主意。我收到很多错误,我用评论标记。 VC11(使用2012年11月的CTP,启用可变参数模板)在除了一个标记区域之外的所有区域中都给出了error C2091: function returns function。最后一个错误是不同的,我在代码中评论其完整描述。 g ++主要提供相同的错误,尽管代码编号不同。

#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)
}

为什么我会收到这些错误?例如,我没有看到参数化构造函数如何返回任何内容,或者数据成员的声明如何返回任何内容。是不是函数指针声明形式的数据成员声明?例如,int (*g)(int);不会声明一个指针指向一个带int并返回int的函数的指针吗?

修改/附录:

我从答案中看到int(int, int)只有一种类型,我需要部分专业才能获得我想要的效果。但是,什么在我的代码中产生错误?如果我评论myfunc = foo,我仍然会收到其他错误。 func<int(int, int)> myfunc;调用默认构造函数。 typename Rint(int, int)实例化,typename... Tn变为空。数据成员R (*fptr)(Tn...);变为R (*fptr)();,因此fptr是一个函数指针,指向一个接受零参数并返回R的函数。如果Rint(int, int),那么R是函数指针类型还是函数类型?如果是后者,那么我可以理解错误消息的上下文。

3 个答案:

答案 0 :(得分:2)

您的类由返回值和参数类型参数化,单独拼写。但是在实例化时,您尝试通过函数类型la std::function对其进行参数化。设为func<int, int, int> myfunc;。通过此更改,您的代码为works

答案 1 :(得分:2)

int(int, int)是一种单一类型。如果你想这样传递它并解开它,你需要部分专业化:

template <typename> struct func;         // leave undefined

template <typename R, typename ...Args>
struct func<R(Args...)>                  // specialized for typename = R(Args...)
{
    // ...
};

答案 2 :(得分:2)

您需要部分专业化。

这是一个有效的例子:

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;
    }
};