【问题标题】:Getting undeclared args when trying to bind std::function using parameter pack尝试使用参数包绑定 std::function 时获取未声明的参数
【发布时间】:2017-11-17 03:55:12
【问题描述】:

我正在尝试创建一个看起来像这样的可变参数模板类:

template <class... Args>
class Message
{
    private:

        std::function<void(Args...)> _function;
    public:
    //stuff

};

我希望有一个绑定选项,以便用户可以在需要时绑定任何函数(带有相应的参数)。我试过这种方法(这个函数是Message类的一部分,所以Args...来自类的模板参数):

    template<class T>
    void Message::bindFunction(void(T::*function)(Args... args), T* ownerPtr)
    {
        //This doesn't work
        _function = boost::bind(function,args, ownerPtr);
    }

但是上面的方法不起作用,我尝试从绑定函数中的 args 创建元组,但编译器一直说:

<args_0> undeclared identifier.

(如果我传递更多参数,它会改变)

从用户的角度来看,它应该是这样的:

class Foo
{
public:

    void test2(int a, float b, double c) 
    {  
        std::cout << "bla";
    }
};

int main()
{
    Foo f;

    Message<int,float,double> Mess;

    Mess.bindFunction(&Foo::test2, &f);
}

我看过很多关于转发参数的文章,但是大多数答案比我已经对不同的模板结构更让我困惑,而没有解释它们。

【问题讨论】:

  • 你已经在使用 C++11; lambda 会比boost::bind(或std::bind,也存在)更直接。
  • @chris 我知道 std::bind 的存在,因为我想为成员函数创建仿函数,所以使用了 boost::bind。
  • @Pins, std::bind 也适用于成员函数。事实上,这是cppreference 上的示例之一。无论如何,除非std::bind_front 成功,否则将可变参数连接到任何一个都是痛苦的。有一个 C++ Weekly 视频介绍了避免 bind 使用 lambda,但听起来一些额外的可变参数模板材料可能会有所帮助。
  • @chris 实际上我以前使用过 std::bind,但是在尝试使用 linux 平台时遇到了一些麻烦(不记得问题),尝试了 boost::bind 然后决定坚持用它。将检查 bind_front。
  • @chris std::bind_front 上周在阿尔伯克基成功通过了 LEWG(图书馆发展工作组)。

标签: c++ c++11 templates variadic-templates variadic-functions


【解决方案1】:

使用 lambda,因为它们更好 (Live Demo (C++11)):

template<class T>
void bindFunction(void(T::*function)(Args...), T* ownerPtr)
{
    _function = [function, ownerPtr](Args... args)
    {
        (ownerPtr->*function)(args...);
    };
}

我们在 lambda 声明中使用[function, ownerPtr] 捕获函数指针和指向类实例的指针。

lambda 接受参数列表,其类型在 Message 类的可变参数模板中指定:Args... args

在内部,我们使用 (ownerPtr-&gt;*function) 语法的实例调用函数,然后通过扩展参数包 (args...) 传入参数

要调用这个函数,你可以这样写:

void callFunction(Args&&... args)
{
    _function(std::forward<Args>(args)...);
}

我们使用perfect forwarding 将我们的参数传递给std::function&lt;void(Args...)&gt; 成员。

【讨论】:

  • 我很惊讶 lambda 在这里工作得多么方便,现在它工作得很好,谢谢。
  • @Pins:使用bind 会非常困难,因为不存在可变参数占位符so you'd have to write your own
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-21
  • 2019-07-18
  • 2018-03-28
  • 2018-09-02
  • 2014-11-06
  • 2022-01-23
  • 2020-07-17
相关资源
最近更新 更多