std :: bind():绑定带有右值引用的lambda [英] std::bind(): bind lambda with rvalue reference as argument
问题描述
我在玩 std :: bind
和右值引用,但我仍然不知道它是如何工作,我有以下代码:
I am playing with std::bind
and rvalue references, but I still don't figure out how it works, I have the following code:
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()
未注释时,以下编译时错误:
When commenting out bind_fun()
, or if the lambda takes Dog&
rather than Dog&&
, the code run fine with expected output. When bind_fun()
is left uncommented, the following compile time error:
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.
我的问题是:
- 为什么
bind_fun()不能被调用(不会编译)在这里使用引用和右值引用作为参数的区别是什么?
- Why
bind_fun()
can not be called(won't compile) when the lambda takes rvalue reference? - What is the difference between using reference and rvalue reference as arguments for the lambda here?
推荐答案
std :: bind
的规范相当密集。简单来说,一个纯绑定参数(不是绑定表达式,不是 reference_wrapper
,而不是占位符)传递给绑定函数 std: :forward vi(tid)
其中 Vi
是 TiD cv&
code> cv 是调用包装器的cv限定符, TiD
是类型 decay_t& ,
,
是
bind
实际传递的类型, tid
是从 std :: forward< Ti>(ti)$ c构造的
类型的左值
$ c>, ti
是传递给 bind
的参数。
The specification for std::bind
is rather dense. In brief, a plain bound argument (not a bind expression, not a reference_wrapper
, and not a placeholder) is passed to the bound function as std::forward<Vi>(tid)
where Vi
is TiD cv &
, cv
is the cv-qualifiers of the call wrapper, TiD
is the type decay_t<Ti>
, Ti
is the type actually passed to bind
, and tid
is "an lvalue of type TiD
constructed from std::forward<Ti>(ti)
", and ti
is the argument passed to bind
.
我们看到 Ti
是 Dog
和 ti
为 Dog(DogABC)
。因此 TiD
也是 Dog
, Vi
c $ c> cv Dog& ,这意味着 std :: forward< Vi>(Tid)
em>,并且编译器抱怨,因为您的lambda是一个右值引用参数,而右值引用参数不能绑定到一个左值。
Applying this to your call, we see that Ti
is Dog
and ti
is Dog("DogABC")
. So TiD
is also Dog
, and Vi
is cv Dog &
, which means that std::forward<Vi>(Tid)
is an lvalue, and the compiler complains because your lambda takes an rvalue reference parameter, and an rvalue reference parameter cannot bind to a lvalue.
这篇关于std :: bind():绑定带有右值引用的lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!