【问题标题】:Assigning a function pointer with variable arguments using parameter pack使用参数包分配具有可变参数的函数指针
【发布时间】:2019-05-22 07:52:50
【问题描述】:

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

我一直在尝试使用的基本结构是这样的

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&lt;int, float&gt;

请参阅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

【问题讨论】:

    标签: c++ parameter-passing


    【解决方案1】:

    问题在于varArgsFunc 是一个模板 不是特定函数,但ArgsFuncPointer&lt;int, float&gt; 是指向特定函数的指针。

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

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

    【讨论】:

    • 其实这不对,看我对问题的更新。问题是函数指针和分配给的函数指针类型之间的签名不同。 std::function 是一个潜在的替代方案,您能否提供一个与上述使用 std::function 等效的示例?
    【解决方案2】:

    你有没有类似的事情

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

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

    【讨论】:

    • 谢谢。我已经解决了我的潜在问题(请参阅更新),但我也意识到 template &lt;typename... Args&gt; class 无法满足我的需要,因为参数包会传播到任何父类,并且事情很快就会变得复杂。我想我需要一个完全不同的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    相关资源
    最近更新 更多