std :: bind():将lambda与rvalue引用绑定为参数

时间:2014-10-11 14:18:03

标签: c++ c++11 lambda stdbind

我正在使用std::bind和rvalue引用,但我仍然无法弄清楚它是如何工作的,我有以下代码:

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.

我的问题是:

  1. 当lambda采用右值引用时,为什么bind_fun()无法被调用(不会被编译)?
  2. 在这里使用reference和rvalue引用作为lambda的参数有什么区别?

1 个答案:

答案 0 :(得分:2)

std::bind的规范相当密集。简而言之,普通绑定参数(不是绑定表达式,不是reference_wrapper,而不是占位符)作为std::forward<Vi>(tid)传递给绑定函数,其中ViTiD cv &cv是调用包装器的cv限定符,TiD是类型decay_t<Ti>Ti是实际传递给bind的类型,tid 1}}是“从TiD”构造的std::forward<Ti>(ti)类型的左值,ti是传递给bind的参数。

将此应用于您的通话,我们发现TiDogtiDog("DogABC")。因此TiD也是DogVicv Dog &,这意味着std::forward<Vi>(Tid)左值,编译器会抱怨因为你的lambda采用rvalue引用参数,而rvalue引用参数不能绑定到左值。