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