【问题标题】:std function reference to member function through std bindstd 函数通过 std 绑定对成员函数的引用
【发布时间】:2020-11-07 17:49:02
【问题描述】:

假设我定义了一个简单的函数引用包装器,如下所示:

struct wrapper {
    std::function<void(void)>& fct;
    
    wrapper(std::function<void(void)>& _fct) : fct{_fct}{
        fct();    
    };
};

当然,实际上它比这更复杂,但我简化了它来说明问题。

然后,我想创建包含函数引用包装器的测试对象:

struct test {
    wrapper myWrapper;
    
    test() : myWrapper{std::bind(&test::boom, this)}{};
    
    void boom() {
        std::cout << "boom()" << std::endl;
    }
    
};

test 对象实例化时,我收到以下错误(请自行尝试here):

 cannot bind non-const lvalue reference of type 'std::function<void()>&' to an rvalue of type 'std::function<void()>'

这是可以理解的,因为std::bind 对象是一个临时的(右值),我无法对其进行引用(我也尝试了没有std::bind 的方法,但没有更好的结果)。另一方面,能够将非静态成员函数引用为std::function 似乎很容易做到,但我无法理解它。

有什么简单的方法可以将非静态成员函数的引用作为std::function&amp;

【问题讨论】:

  • 那是因为左值引用不能绑定到临时对象(并且您的 bind 返回值是临时的)。你为什么要做参考?只需复制一个函数对象。如果必须取引用,请获取 const 左值引用或左值引用。
  • 您不需要引用std::functionstd::function 本身将“引用”您要调用的函数
  • 现实生活中的用例是通过嵌入式 RTOS 多线程 + CRTP。因此,我无法承担复制 std::function 的成本(请参阅stackoverflow.com/questions/44388849)。我在这里简化了很多:)
  • 搬家的费用你能承担吗?这是最简单的出路。并且编译器应该优化移动,如果它可以看到端点(分配给类成员) - 标题中的内联构造函数声明。如果没有,您可以使用引用,但您需要确保 std::bind 结果将比您的类对象寿命更长。
  • 正是错误消息所说的 ;) 非 const 引用只能分配给命名对象,分配给临时对象没有意义 - 对存在的对象进行更改有什么意义仅在当前功能中?然而,常量引用可以绑定到一个临时(未命名)对象,它们会延长该对象的生命周期,直到函数返回。这使您可以将 const ref 参数与左值和右值一起使用。这不会扩展到类成员,因此您不能使用此技巧将 fct 初始化为临时。

标签: c++ function reference wrapper composition


【解决方案1】:

通过“类型化绑定”的这种“原始”实现,我可以问:保存“test*”指针的内存将由包装器存储在哪里?以及 bindex 如何知道在 where call ->first 中将转换哪种类型?这个bindex应该被类型擦除吗?

struct bindx : pair<void(test::*)(void), test*> {
    using pair<void(test::*)(void), test*>::pair;
    void operator()() { (second->*first)(); }
};

struct wrapper {
    bindx f_;
    
    wrapper(bindx f) : f_{f}{
        f_();    
    };
};

struct test {
    wrapper myWrapper;
    
    test() : myWrapper( bindx{&test::boom, this} ) {};
     . . .
}

http://coliru.stacked-crooked.com/a/a40f432aad928908

【讨论】:

    猜你喜欢
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多