1

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 R被实例化为int(int, int),并typename... Tn变为空。数据成员R (*fptr)(Tn...);变为R (*fptr)();fptr因此是一个函数指针,它指向一个函数,该函数接受零参数并返回一个R。如果Rint(int, int),那么是R函数指针类型还是函数类型?如果是后者,那么我可以理解错误消息的上下文。

4

3 回答 3

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;
    }
};
于 2013-10-31T00:02:42.200 回答
2

您的类由返回值和参数类型参数化,分别说明。但是在实例化时,您尝试通过函数类型 a la 对其进行参数化std::function。让它func<int, int, int> myfunc;。通过此更改,您的代码可以正常工作

于 2013-10-30T23:55:26.653 回答
2

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

template <typename> struct func;         // leave undefined

template <typename R, typename ...Args>
struct func<R(Args...)>                  // specialized for typename = R(Args...)
{
    // ...
};
于 2013-10-30T23:59:29.120 回答