一千萬個為什麽

搜索

C ++ 14中的泛型lambdas:奇怪的行為

maybe there's something I didn't fully get, however after reading "Use decltype on auto&& parameters to std::forward them" (from Effective Modern C++) I found something really weird.

假設我們有

int size(std::string &&s) { std::cout <<"std::string&&" <<<"std::string const &" <

I defined two lambas (one with auto, and one that correctly forward an auto&& param):

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

std::string s{ "buonanotte" };
std::cout <<<<(x)); };
std::cout <<<<

Well, the results are the same: f(s) and g(s) call size(const std::string&), while f("fiorellino") and g("fiorellino") call the overload of size for rvalues.

My question is: why is this happening? Shouldn't only the second lambda be able to distinguish between an lvalue and rvalue? I was expecting the first lambda (f()) calling twice size(const std::string&), but apparently this is not happening.

難道我做錯了什麽?

最佳答案

好,

so I'd like to publish a full answer (Michael, again, thanks). The thing I was getting confused was that "fiorellino" is an rvalue and a temporary is created for it and this temporary object, when a const T& and a T&& are available it will always bind to the T&& version. So far so good. This makes sense in effect (see http://en.cppreference.com/w/cpp/language/value_category where rvalues are described).

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

int size(std::string &&s) { std::cout <<"std::string&&" <<<"std::string const &" <<<"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(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));

現在生成(123)創建一個正確的臨時的,將被第一個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&&

even if I used std::move(s) (which creates an rvalue-reference) the first lambda always selects the const T& overload.

轉載註明原文: C ++ 14中的泛型lambdas:奇怪的行為