簡體   English   中英

c ++ 14中的泛型lambda:奇怪的行為

[英]Generic lambdas in c++14: weird behavior

也許有一些我沒有完全得到的東西,但是在閱讀“使用decltype on auto && parameters to std :: forward them”(來自Effective Modern C ++)后,我發現了一些非常奇怪的東西。

我們假設有

int size(std::string &&s) { std::cout <<"std::string&&" <<std::endl; return s.size(); }
int size(const std::string &s) { std::cout <<"std::string const &" <<std::endl; return s.size(); }

我定義了兩個lambas(一個用auto,一個用於正確轉發auto && param):

auto f = [](auto x) { return size(x); };

std::string s{ "buonanotte" };
std::cout <<f(s) <<std::endl;
std::cout <<f("fiorellino") <<std::endl;

auto g = [](auto&& x) { return size(std::forward<decltype(x)>(x)); };
std::cout <<g(s) <<std::endl;
std::cout <<g("fiorellino") <<std::endl;

好吧,結果是相同的:f(s)和g(s)調用大小(const std :: string&),而f(“fiorellino”)和g(“fiorellino”)調用rvalues的大小重載。

我的問題是:為什么會發生這種情況? 不僅第二個lambda能夠區分左值和右值嗎? 我期待第一個lambda(f())調用兩次大小(const std :: string&),但顯然這沒有發生。

難道我做錯了什么?

不僅第二個lambda能夠區分左值和右值嗎? 我期待第一個lambda(f())調用兩次大小(const std :: string&)

字符串文字"fiorellino"是一個左值,但是當它傳遞給size ,將從該字符串文字構造一個臨時的std::string對象,該臨時值是一個右值。

也就是說, ff("fiorellino")x類型將是const char* f調用size時, const char*用於創建臨時std:string (rvalue)。

這反過來導致為f("fiorellino")選擇rvalue過載,基於此: “當用作函數參數並且當函數的兩個重載可用時,一個采用rvalue引用參數,另一個采用左值引用const參數,rvalue綁定到右值引用過載“ )。

好,

所以我想發表一個完整的答案(Michael,再次,謝謝)。 令我感到困惑的是,“fiorellino”是一個右值,為它和這個臨時對象創建了一個臨時對象,當const T&和T &&可用時,它將始終綁定到T &&版本。 到現在為止還挺好。 這實際上是有意義的(參見http://en.cppreference.com/w/cpp/language/value_category ,其中描述了rvalues)。

我現在用這種方式改變了我的例子:

int size(std::string &&s) { std::cout <<"std::string&&" <<std::endl; return s.size(); }
int size(const std::string &s) { std::cout <<"std::string const &" <<std::endl; return s.size(); }

std::string generate(int x) { return std::to_string(x); }

auto f = [](auto x) { return size(x); };

std::string s{ "buonanotte" };
std::cout <<"f(): "; f(s);
std::cout <<"f(): "; f("fiorellino");
std::cout <<"f(): "; f(generate(123));
std::cout <<"f(): "; f(std::move(s));

auto g = [](auto&& x) { return size(std::forward<decltype(x)>(x)); };

std::string s2{ "buonanotte" };
std::cout <<"g(): "; g(s2);
std::cout <<"g(): "; g("fiorellino");
std::cout <<"g(): "; g(generate(123));
std::cout <<"g(): "; g(std::move(s2));

現在,generate(123)創建了一個正確的臨時,它將被第一個lambda錯誤地轉發,但是被第二個lambda正確轉發。

看看輸出:

f(): std::string const &
f(): std::string&&
f(): std::string const &
f(): std::string const &
g(): std::string const &
g(): std::string&&
g(): std::string&&
g(): std::string&&

即使我使用std :: move(s)(創建一個rvalue-reference),第一個lambda總是選擇const T&overload。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM