std :: bind():绑定带有右值引用的lambda [英] std::bind(): bind lambda with rvalue reference as argument

查看:778
本文介绍了std :: bind():绑定带有右值引用的lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在玩 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.

我的问题是:


  1. 为什么 bind_fun()不能被调用(不会编译)在这里使用引用和右值引用作为参数的区别是什么?

  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?


推荐答案

std :: bind 的规范相当密集。简单来说,一个纯绑定参数(不是绑定表达式,不是 reference_wrapper ,而不是占位符)传递给绑定函数 std: :forward vi(tid)其中 Vi TiD cv& code> cv 是调用包装器的cv限定符, TiD 是类型 decay_t& , bind 实际传递的类型, tid 是从 std :: forward< Ti>(ti)类型的左值 $ 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆