2014-10-11 141 views
1

我玩std::bind和右值引用,但我還是不弄清楚它是如何工作的,我有以下代碼:的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()不能稱爲(不會編譯)當拉姆達需要右值的參考?
  2. 使用引用和右值引用作爲lambda的參數在這裏有什麼區別?
+0

'std :: bind'將綁定的參數作爲左值傳遞,因此它與右值引用不匹配。 – 2014-10-11 14:25:22

回答

2

std::bind的規格相當密集。簡言之,一個普通的結合參數(不是bind表達式,而不是一個reference_wrapper,而不是一個佔位符)被傳遞至所結合的功能std::forward<Vi>(tid)其中ViTiD cv &cv是呼叫包裝紙的cv修飾符,TiD是類型decay_t<Ti>,Ti是實際傳遞給bind的類型,並且tid是「從std::forward<Ti>(ti)構造的類型TiD的左值」,並且ti是傳遞給bind的參數。

將此應用於您的通話,我們看到TiDogtiDog("DogABC")。所以TiDDog,並Vicv Dog &,這意味着std::forward<Vi>(Tid)左值和編譯器會抱怨,因爲您的拉姆達需要一個右值引用參數,和右值引用參數不能綁定到左值。

+0

哇相當複雜,但對我有意義,非常感謝! – neevek 2014-10-11 15:13:01