В соответствии с [over.over]/2, мы выполняем аргумент шаблона вычет. Это будет успешным для всех трех перегрузок: в первом, держать [temp.deduct.funcaddr]/2 в виде:
Тип заполнителя (7.1.7.4) в типе возвращаемого шаблона функции не является вывести контекст. Если для такой функции успешно завершен вывод аргумента , тип возврата определяется из экземпляра тела функции .
Поскольку вывод будет успешным (учитывая, что все параметры шаблона содержат явно аргументы), тип возврата выводится как int
. Во втором случае вывод преуспевает, поскольку аргумент предоставляется, а в третьем - T
. & кинжал;
Переходя к paragraph 4,
Если выбрано более одной функции, [...] любой данный функция специализация шаблона F1
устраняется, если набор содержит второй шаблон функции специализации, функция которой шаблон более специализированный, чем шаблон функции F1
в соответствии с правилами частичного порядка заказа 14.5.6.2. После таких исключений, если таковые имеются, , должна оставаться одна выбранная функция.
Согласно [temp.deduct.partial]/3, типам функций функции шаблонов используются для частичного упорядочения. Мы можем сразу увидеть, что типы функций # 1 и # 2 не содержат параметров шаблона, которые участвуют в вычете, поэтому с помощью добавления к [temp.deduct.partial]/4, введенного по основному выпуску 1391, их соответствующие P
s не используются для определения порядка. @bogdan объяснил here, почему это разрешение проблематично; нижняя строка заключается в том, что упорядочение просто дает двусмысленность для # 1 и # 2.
То есть, согласно действующей (возможно, дефектной) формулировке, преобразование во всех случаях плохо сформировано. Если частичное упорядочение фиксируется для пар, не зависящих от/выводящих параметров,
- случай 1 и 3 являются неоднозначными, потому что для двух не зависимых типов функций (те из # 1 и # 2), нет заказывающая пара.
- Принятое поведение в случае 2 является правильным (как и ожидалось).
& крестик;[temp.deduct.type]/8 элемент 9 (T()
), в случае, если вам было любопытно.
Не определяет 1 и 2 в одном и том же блоке перевода нарушение ODR? – user657267
Если «auto» переводится как «int», то # 1 и # 2 совпадают, да? Не предпочтительный кандидат. Кланг, по-видимому, рассматривает № 2 более специализированную, чем # 1 и # 1 и # 3 ту же специализацию; неоднозначный выбор снова. Я бы сказал, что gcc прав, а Clang ошибочен из-за «авто», не должен участвовать в разрешениях перегрузки. – Ripi2
@ user657267 Типы возврата являются частью подписи шаблонов функций. Вышеуказанные декларации предоставляют разные типы * декларируемых * возвратов, поэтому подписи различаются. То, что фактические типы возврата совпадают, не имеет значения. – Columbo