使用参数包为函数指针分配变量参数

时间:2019-05-22 07:52:51

标签: c++ parameter-passing

我想将一个指向函数的指针存储为成员变量,该函数可以使用可变数量的不同类型的参数。

我一直在尝试使用的基本构造是

template <typename... Args>
using ArgsFuncPointer = void(*)(Args...);

template<typename... Args> void varArgsFunc(Args&&... args) {  }

{
    ArgsFuncPointer<int, float> funcPointer = varArgsFunc;   
    funcPointer(1, 2.0);
}

问题是varArgsFunc无法转换为ArgsFuncPointer<int, float>

有关(不起作用的)示例,请参见coliru

最终,我希望能够执行以下操作:

template <typename... Args> class Foo
{
public:
    Foo(Args&&... args)
    {
        func(args);
    }

    VarArgsFuncPointer func;
}

更新

事实证明,无法编译的原因是ArgsFuncPointervarArgsFunc之间的签名存在细微差异。对于ArgsFuncPointer,参数包是通过右值引用传递的,而对于varArgsFunc,参数包是按值传递的。

这有效:

template <typename... Args>
using ArgsFuncPointer = void(*)(Args&&...);

template<typename... Args> void varArgsFunc(Args&&... args) {  }

{
    ArgsFuncPointer<int, float> funcPointer = varArgsFunc;   
    funcPointer(1, 2.0);
}

工作示例here

2 个答案:

答案 0 :(得分:3)

问题在于varArgsFunc模板而不是特定功能,而ArgsFuncPointer<int, float>是指向特定功能的指针。

未经测试,但是您应该能够通过指定其模板参数来指定实际的函数实例:

ArgsFuncPointer<int, float> funcPointer = varArgsFunc<int, float>;
//                                                   ^^^^^^^^^^^^
//                                Must specify template arguments

另一方面,我建议您使用std::function而不是指向非成员函数的指针。这样您就可以使用std::bindlambdas或几乎任何可调用对象。

使用std::function与您现在所拥有的非常相似:

template <typename... Args>
using ArgsFuncPointer = std::function<void(Args...)>;

然后使用lambda可以执行类似的操作

ArgsFuncPointer<int, float> funcPointer = [](int i, float f)
{
    varArgsFunc(i, f);  // Call the real function
};

答案 1 :(得分:1)

您在做类似的事情吗

template <typename... Args>
using ArgsFuncPointer = void(*)(Args...);

template <typename... Args> class Foo
{
public:
    Foo(Args&&... args)
    {
        func(std::forward<Args>(args)...);
    }

    ArgsFuncPointer<Args...> func;
};

在表达式中使用包时需要扩展。