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

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

本文关键字:函数 包装 对象 通过 可变      更新时间:2023-10-16

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 << "foon";
    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的函数。如果R int(int, int),那么R是函数指针类型还是函数类型?如果是后者,那么我可以理解错误消息的上下文。

int(int, int)是一种

类型。如果你想像这样传递它并解开它,你需要部分专业化:

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

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

你需要部分专业化。

下面是一个工作示例:

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