Ответ 1
Это интересно. Существует два способа прочитать критическую часть раздела 13.3.3. Исходный пример должен обязательно вызвать шаблон функции, но версия, в которой удаляется один из не-шаблонов, может считаться неоднозначной.
13.3.3:
Жизнеспособная функция
F1
определяется как лучшая функция, чем другая жизнеспособная функцияF2
, если для всех аргументов я ICS_i (F1
) не является худшей последовательностью преобразования, чем ICS_i (F2
), и затем
для некоторого аргумента j, ICS_j (
F1
) является лучшей последовательностью преобразования, чем ICS_j (F2
), или, если не это,контекст представляет собой инициализацию путем пользовательского преобразования (см. 8.5, 13.3.1.5 и 13.3.1.6) и стандартную последовательность преобразования из возвращаемого типа
F1
в тип назначения (т.е. тип инициализируемого объекта) является лучшей последовательностью преобразования, чем стандартная последовательность преобразования из возвращаемого типаF2
в тип назначения, или, если это не так,
F1
- функция без шаблона, аF2
- специализированная функция шаблона или, если не это,
F1
иF2
являются специализированными шаблонами функций, а шаблон функции дляF1
более специализирован, чем шаблон дляF2
в соответствии с правилами частичного упорядочения, описанными в 14.5.6.2.Если существует только одна жизнеспособная функция, которая является лучшей функцией, чем все другие жизнеспособные функции, то она выбирается с помощью разрешения перегрузки; иначе звонок плохо сформирован.
В примере clang правильно идентифицирует набор из трех жизнеспособных функций-кандидатов:
C::operator int()
C::operator bool()
C::operator double<double>()
Третий - это специализированная функция. (Я не думаю, что синтаксис выше является законным, но вы получаете идею: в этот момент разрешения перегрузки он не рассматривается как шаблон, а как специализация с определенным типом функции.)
Единственная неявная последовательность преобразования в аргументах здесь (ICS1) - это точное соответствие "lvalue C
" на "C&
" для неявного параметра, поэтому это не будет иметь значения.
Этот пример - это точно ситуация, описанная во втором марке, поэтому функция, возвращающая double
, явно лучше, чем две другие.
Здесь, где это становится странным: по буквальному чтению, operator int
также лучше, чем специализация шаблона, из-за третьей пули. "Подождите, не лучше, чем" быть антисимметричным ". Как вы можете сказать F1
лучше, чем F2
И F2
лучше, чем F1
?" К сожалению, Стандарт явно не говорит ничего подобного. "Разве вторая пуля не имеет приоритета над третьей пулей из-за фразы" если не эта "? Да, для констант F1
и F2
. Но в Стандарте не говорится, что выполнение второй пули для (F1,F2)
делает третью пулю для (F2,F1)
неприменимой.
Конечно, поскольку operator int
не лучше, чем operator bool
и наоборот, существует еще "одна жизнеспособная функция, которая является лучшей функцией, чем все другие жизнеспособные функции".
Я не совсем одобряю это странное чтение, за исключением, возможно, сообщения об этом как о стандартном дефекте. Переход с этим имел бы странные последствия (например, удаление перегрузки, которая не была лучшей из этого примера, изменяет программу от хорошо сформированной до двусмысленной!). Я думаю, что цель состоит в том, чтобы вторая пуля была рассмотрена в обоих направлениях, прежде чем третья пуля будет рассмотрена вообще.
Что означало бы, что шаблон функции должен быть выбран с помощью разрешения перегрузки, и это ошибка clang.