1

我正在使用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.

我的问题是:

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

1 回答 1

2

的规范std::bind相当密集。简而言之,一个普通的绑定参数(不是绑定表达式,不是 a reference_wrapper,也不是占位符)被传递给绑定函数std::forward<Vi>(tid)where Viis TiD cv &cv是调用包装器的 cv-qualifiers ,TiD是 type decay_t<Ti>Ti是实际传递的类型to bind,并且是“从”构造tid的类型的左值,并且是传递给的参数。TiDstd::forward<Ti>(ti)tibind

将此应用于您的电话,我们看到TiisDogtiis Dog("DogABC")。所以TiDisDogViis cv Dog &,这意味着它std::forward<Vi>(Tid)是一个左值,编译器会抱怨,因为你的 lambda 需要一个右值引用参数,而右值引用参数不能绑定到左值。

于 2014-10-11T14:59:13.430 回答