我正在玩 std::bind
和右值引用,但我仍然不知道它是如何工作的,我有以下代码:
class Dog {
public:
Dog(const string &name) : name_(name) {
cout << "Dog::ctor" << endl;
}
string GetName() {
return name_;
}
private:
string name_;
};
auto bind_fun = bind([](Dog &&d){ cout << d.GetName() << endl; }, Dog("DogABC"));
bind_fun();
当注释掉 bind_fun()
时,或者如果 lambda 使用 Dog&
而不是 Dog&&
,代码运行正常,输出符合预期。当 bind_fun()
未被注释时,出现以下编译时错误:
test3.cpp:109:3: error: no matching function for call to object of type 'std::__1::__bind<<lambda at test3.cpp:108:17>, Dog>'
f();
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/functional:1749:9: note: candidate template ignored: substitution failure [with _Args = <>]: implicit instantiation of undefined template
'std::__1::__bind_return<<lambda at test3.cpp:108:17>, std::__1::tuple<Dog>, std::__1::tuple<>, false>'
operator()(_Args&& ...__args)
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/functional:1758:9: note: candidate template ignored: substitution failure [with _Args = <>]: implicit instantiation of undefined template
'std::__1::__bind_return<const <lambda at test3.cpp:108:17>, const std::__1::tuple<Dog>, std::__1::tuple<>, false>'
operator()(_Args&& ...__args) const
^
1 error generated.
我的问题是:
- 为什么当 lambda 取右值引用时
bind_fun()
不能被调用(不能编译)? - 这里使用引用和右值引用作为 lambda 的参数有什么区别?
最佳答案
std::bind
的规范比较密集。简而言之,一个普通的绑定(bind)参数(不是绑定(bind)表达式,不是 reference_wrapper
,也不是占位符)作为 std::forward<Vi>(tid)
传递给绑定(bind)函数。其中 Vi
是TiD cv &
, cv
是调用包装器的 cv 限定符,TiD
是类型 decay_t<Ti>
, Ti
是实际传递给 bind
的类型, 和 tid
是“TiD
类型的左值,由std::forward<Ti>(ti)
构造”,和ti
是传递给 bind
的参数.
将此应用于您的通话,我们看到 Ti
是Dog
和 ti
是Dog("DogABC")
.所以TiD
也是Dog
, 和 Vi
是cv Dog &
,这意味着 std::forward<Vi>(Tid)
是一个左值,编译器会报错,因为你的 lambda 接受了一个右值引用参数,而右值引用参数不能绑定(bind)到一个左值。
关于c++ - std::bind():以右值引用作为参数绑定(bind) lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26315604/