Overload resolution between const lvalue reference and rvalue reference
Asked Answered
B

3

5
#include <iostream>
#include <string>

void fnc (const std::string&)
{
    std::cout<<1;
}

void fnc (std::string&&)
{
    std::cout<<2;
}

int main()
{
    fnc ("abc");
}

All the compilers choose std::string&& version of fnc, and it is logical, because the temporary std::string is created for a reference binding, but I can't find, where is it described in C++ 14 Standard. I found one paragraph in there (3.2):

— Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if

[...]

— S1 and S2 are reference bindings (8.5.3) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference

But it isn't that case, because S1 binds an rvalue reference to an lvalue ("abc", lvalue of const char[4]). Where can I find description, by which the second overload is selected?

P.S. I pointed to C++14 Standard instead of C++11, because I know, that there was some defect reports in C++11, linked with rvalue reference binding.

Bodice answered 12/11, 2016 at 15:57 Comment(0)
D
7

First the compiler performs an implicit array-to-pointer conversion for "abc", so the type of "abc" becomes const char*. Second (and you probably missed that), const char* is converted to a rvalue std::string via the const char* non-explicit constructor of std::string (# 5 in the link). The constructed std::string rvalue is a perfect match for the second overload, so the second overload is chosen.

Discernible answered 12/11, 2016 at 16:12 Comment(0)
F
2

But it isn't that case, because S1 binds an rvalue reference to an lvalue ("abc", lvalue of const char[4]).

Note that "abc" is a const char[4], not a std::string. But both fnc() take std::string as parameter, and references can't be bound to objects with different type directly. Therefore firstly "abc" needs to be implicitly converted to std::string, which is a temporary, i.e. an rvalue. Then as the stardard says, the rvalue reference overload will be selected.

Fortunna answered 12/11, 2016 at 16:14 Comment(0)
I
1

"abc" cannot be passed directly into either overload of fnc(). For both of them it must be converted to an (rvalue) std::string. But then the cited rule from the standard unequivocally selects fnc(std::string&&) over fnc(const std::string&).

Ignoble answered 12/11, 2016 at 16:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.