std::bind(): bind lambda with rvalue reference as argument

空扰寡人 提交于 2020-01-23 03:27:28

问题


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(); 

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.

My questions are:

  1. Why bind_fun() can not be called(won't compile) when the lambda takes rvalue reference?
  2. What is the difference between using reference and rvalue reference as arguments for the lambda here?

回答1:


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.

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.



来源:https://stackoverflow.com/questions/26315604/stdbind-bind-lambda-with-rvalue-reference-as-argument

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!