Перегрузка шаблонов функций преобразования

Рассмотрим следующее:

struct X {
    template <class T> operator T();  // #1
    template <class T> operator T&(); // #2
};

int        a = X{}; // error: ambiguous
int&       b = X{}; // calls #2
int const& c = X{}; // calls #2

Ситуация для b проста, #2 является единственным жизнеспособным кандидатом. Каково правило, указывающее, что #2 предпочтительнее #1 для инициализации int const&, но два являются неоднозначными для инициализации int?

Ответы

Ответ 1

При выборе инициализации ссылки, заданной ее инициализатором, сначала проверяется прямое связывание. [dcl.init.ref]/(5.1.2):

Если ссылка является ссылкой lvalue, а выражение инициализатора [...] имеет тип класса (т.е. T2 - тип класса), где T1 не ссылается на T2 и может быть преобразуется в lvalue типа "cv3 T3", где "cv1 T1" является ссылочным-совместимым с "cv3 T3" (это преобразование выбирается путем перечисления применимых функций преобразования (13.3.1.6) и выбрав лучший из них с помощью разрешения перегрузки (13.3)), тогда ссылка привязана [...] к результату lvalue преобразования [...].

Формулировка, определяющая выбор кандидата для этого процесса (13.3.1.6, как упоминалось выше) исключает первую функцию преобразования:

Рассматриваются функции преобразования S и его базовые классы. Те неявные функции преобразования которые не скрыты внутри S и выдают тип "lvalue reference to cv2 T2" (при инициализации ссылки на lvalue или ссылкой на функцию rvalue) [...], где "cv1 T" является ссылкой -совместимый (8.6.3) с "cv2 T2", - это функции-кандидаты. Для прямой инициализации [...].

Ясно, что это исключение специфично для семантики инициализации ссылок, поэтому первый случай еще неоднозначен.