4
void func(const int &) { std::cout << "c lv ref\n"; } 
void func(int &&) { std::cout << "rv ref\n"; } 

func(1); 

Поскольку константная ссылка Lvalue способен принимать все типы данных (сопзИте и не- lval, сопзИте и не- RValue), интересно, что является гарантия того, что приведенный выше код будет печатать «rv ref». Является ли он стандартизованным или зависит от компилятора?перегруженных функции приоритета (ссылки)

ответ

6

Моего предыдущее объяснение было неправильным, - как T.C. mentioned in the comments, оба перегруженных имеют одинаковое неявного последовательность преобразование и неоднозначность происходит в специальном тай-брейке, определенном в стандарте.


§13.3.3.1.4[over.ics.ref], пар. 1

Когда параметр ссылочного типа соединяется непосредственно ([dcl.init.ref]) к выражению аргумента, неявная последовательность преобразования является преобразованием идентичности, если выражение аргумента не имеет типа, который производный класс типа параметра, и в этом случае неявная последовательность преобразования представляет собой преобразование с производной базой ([over.best.ics]). [...]

Если типы аргументов одинаковы, последовательностьнеявного преобразования применяется к обоим перегрузкам является преобразованиемидентичности. Это еще не устраняет неоднозначность этих двух функций.

неоднозначность определяется как связующий выключатель здесь:

§13.3.3.2[over.ics.rank], пар 3.2.3

[Стандартной последовательность преобразования S1 является лучшим преобразованием чем стандартная последовательность преобразования S2, если ...]S1 и S2 являются ссылочными связями ([dcl.init.ref]), и ни один из них не ref ers для неявного параметра объекта нестатической функции-члена, объявленной без ref-квалификатора, и S1 связывает ссылку rvalue с rvalue, а S2 связывает ссылку lvalue. [...]

Кавычки означают, что в случае двух последовательностей неявные преобразования идентичности:

  • Последовательность связывания RValue для RValue ссылки является лучшим вариантом.

  • Последовательность, связывающая значение rvalue с ссылочным значением lvalue, хуже, чем упомянутая выше.


[...], если S1 и S2 ссылкой связывания [...]

Причина, почему const требуется для связывания с rvalues ​​const& можно найти здесь:

§8.6.3[dcl.init.ref], пар 5,2

Ссылка тип «cv1 T1» инициализируется выражением типа «cv2 T2» следующим образом:

[Если ссылка именующая ссылка и выражение инициализатора ...]

В противном случае, ссылка должна быть именующей ссылкой на энергонезависимый тип сопзЬ (т.е. CV1 должна быть константной), или ссылка должна быть ссылкой rvalue.

Если выражение инициализатора [...] является Rvalue (но не битовое поле) или функции Левого и «CV1 Т1» является ссылкой совместит с «CV2 Т2»

+0

спасибо! Теперь все ясно – Criss

+0

Нет, это не то, как это работает. В обоих случаях есть ICS (если вы не можете создать ICS, функция не является жизнеспособной), и оба являются преобразованием идентичности. Это контролируется тай-брейкером в [\ [over.ics.rank \] /3.2.3] (https://timsong-cpp.github.io/cppwp/over.ics.rank#3.2.3). –

+0

@ T.C. Я не понимал этот стандарт. Извинения за распространение дезинформации - я отредактировал вопрос, надеясь сделать его правильным. –

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

  • Нет связанных вопросов^_^