2016-11-12 7 views
3
#include <iostream> 
#include <string> 

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

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

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

Всех компиляторы выбирают std::string&& версии fnc, и это логично, потому что временная std::string создается для ссылки связывания, но я не могу найти, где это описанных в стандарте C++ 14. я нашел один абзац там (3.2):разрешения перегрузки между константной ссылкой Lvalue и ссылкой RValue

- Стандартная последовательность преобразования S1 является лучшей последовательностью преобразования, чем стандартной последовательность преобразования S2, если

[...]

- S1 и S2 являются ссылочными привязками (8.5.3), и ни один из них не ссылается на параметр неявного объекта нестатической функции-члена, объявленный без рефлектоватора, и S1 связывает ссылку rvalue с rvalue и S2 связывается именующим присвоенный

Но это не тот случай, так как S1, связывает ссылку RValue к именующему («ABC», именующей постройка полукокса [4]). Где я могу найти описание, по которому выбрана вторая перегрузка?

P.S. Я указал на C++ 14 Standard вместо C++ 11, потому что знаю, что в C++ 11 были некоторые отчеты о дефектах, связанные с привязкой ссылки rvalue.

ответ

6

Сначала компилятор выполняет неявное преобразование матрицы в указатель для "abc", поэтому тип "abc" становится const char*. Второй (и вы, вероятно, пропустили это), const char* преобразуется в rvaluestd::string через const char*non-explicit constructor of std::string (№ 5 в ссылке). Построенное std::string rvalue идеально подходит для второй перегрузки, поэтому выбрана вторая перегрузка.

+3

Это преобразование между массивами и указателями, а не l-to-r. –

+0

@ T.C. Да, вы правы, исправлены. – vsoftco

1

Но это не тот случай, потому что S1 связывает ссылку rvalue с lvalue ("abc", lvalue const char [4]).

Обратите внимание, что "abc" является const char[4], не std::string. Но как fnc() принимают std::string как параметр, а ссылки не могут быть привязаны к объектам с различным типом напрямую. Поэтому сначала "abc" должно быть неявно преобразовано в std::string, что является временным, то есть значением. Затем, как говорит стажер, будет выбрана эталонная перегрузка rvalue.

1

"abc" не может быть передан непосредственно в перегрузку fnc(). Для обоих из них он должен быть преобразован в (rvalue) std::string. Но тогда приведенное правило со стандарта однозначно выбирает fnc(std::string&&) за fnc(const std::string&).

Смежные вопросы