2016-12-16 9 views
8

С 3 следующих перегрузкамиперегрузки функции шаблона с автоматическим

template <class T> auto foo() { return 1; } 
template <class T> int foo() { return 2; } 
template <class T> T foo() { return 3; } 

ли следующее плохо формируется?

static_cast<int(*)()>(&foo<int>)(); 

Clang выбирает перегрузки # 2, в то время как GCC не может скомпилировать (Demo)

При снятии перегрузки # 1, оба согласны с тем, чтобы выбрать перегрузки # 2 (Demo).

При снятии перегрузки # 2, GCC выбирает перегрузки # 1 и лязг не удается скомпилировать (Demo)

+6

Не определяет 1 и 2 в одном и том же блоке перевода нарушение ODR? – user657267

+0

Если «auto» переводится как «int», то # 1 и # 2 совпадают, да? Не предпочтительный кандидат. Кланг, по-видимому, рассматривает № 2 более специализированную, чем # 1 и # 1 и # 3 ту же специализацию; неоднозначный выбор снова. Я бы сказал, что gcc прав, а Clang ошибочен из-за «авто», не должен участвовать в разрешениях перегрузки. – Ripi2

+2

@ user657267 Типы возврата являются частью подписи шаблонов функций. Вышеуказанные декларации предоставляют разные типы * декларируемых * возвратов, поэтому подписи различаются. То, что фактические типы возврата совпадают, не имеет значения. – Columbo

ответ

8

В соответствии с [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()), в случае, если вам было любопытно.

+0

Chapeau. Очень интересно. Вы знаете стандарт наизусть, и это немного пугает меня ... :-) +1 – skypjack