const 左值引用和右值引用之间的重载解析

Overload resolution between const lvalue reference and rvalue reference

#include <iostream>
#include <string>

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

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

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

所有编译器都选择 fncstd::string&& 版本,这是合乎逻辑的,因为临时 std::string 是为引用绑定创建的,但我找不到,在哪里它是在 C++ 14 标准中描述的吗? 我在那里找到了一段 (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

但事实并非如此,因为 S1 将右值引用绑定到 左值 ("abc",const char[4] 的左值)。 我在哪里可以找到选择第二个重载的描述?

P.S。我指的是 C++14 标准而不是 C++11,因为我知道 C++11 中有一些缺陷报告,与右值引用绑定相关联。

首先,编译器为"abc"执行隐式数组到指针的转换,因此"abc"的类型变为const char*。其次(您可能错过了),const char* 通过 const char* non-explicit constructor of std::string(# 5 in link)。构造的 std::string 右值与第二次重载完美匹配,因此选择第二次重载。

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

请注意 "abc"const char[4],而不是 std::string。但是fnc()都以std::string作为参数,引用不能直接绑定到不同类型的对象上。因此首先需要将"abc"隐式转换为std::string,这是一个临时的,即一个右值。然后正如标准所说,将选择右值引用重载。

"abc" 不能直接传递到 fnc() 的任一重载中。对于它们两者,都必须将其转换为(右值)std::string。但是随后标准中引用的规则明确选择 fnc(std::string&&) 而不是 fnc(const std::string&).