Разрешение перегрузки шаблона функции, зависимые и независимые параметры - PullRequest
8 голосов
/ 16 июня 2020

Учитывая следующую программу

#include <iostream>

template<class T> struct id { using type = T; };

template<class T1, class T2>
int func(T1, T2) { return 0; }

template<class T1, class T2>
int func(typename id<T1>::type, typename id<T2>::type) { return 1; }

int main()
{
    std::cout << func<int, int>(0, 0) << std::endl;
}

G CC и Clang, обе печатают 1 для этой программы. Гарантированно ли эта программа печатает 1 по стандарту?

Я пытался найти здесь ответ, но не смог его расшифровать. Похоже, что шаблоны функций могут быть эквивалентными и поэтому нарушают ODR, но я не уверен.

Имеет ли значение изменение второго шаблона функции на

template<class T>
using id_type = typename id<T>::type;

template<class T1, class T2>
int func(id_type<T1>, id_type<T2>) { return 1; }

?

Ответы [ 2 ]

4 голосов
/ 16 июня 2020

Это частичный заказ болотного стандарта. Мы подставляем уникальные типы в один из шаблонов функций и пытаемся вывести другой из них. Делайте это обоими способами, и если дедукция успешна только в одном направлении, у нас есть порядок. Если вы хотите прочитать тайные правила, см. [Temp.fun c .order] и [temp.deduct.partial].

Итак, здесь

  • Подстановка T1=U1, T2=U2 в первом типе функции перегрузки производит int f(U1, U2); Можем ли мы вывести из этого T1 и T2 во второй перегрузке? Нет; оба находятся в невыведенных контекстах. Er go, вывод не выполняется.
  • Подстановка T1=U1, T2=U2 во вторую перегрузку дает int f(id<U1>::type, id<U2>::type) (это выполняется в контексте определения, поэтому мы не можем заменить id) - может быть специализация где-нибудь). Можем ли мы вывести из этого значения T1 и T2 в первой перегрузке? Да, путем вывода T1 = id<U1>::type и T2 = id<U2>::type. Дедукция успешна.

Поскольку дедукция успешна только в одном направлении - выведение первого из преобразованного второго - второе более специализировано, чем первое, и предпочтительно выбирается разрешением перегрузки.

Случай шаблона псевдонима ничего не меняет.


Эти шаблоны не эквивалентны и не эквивалентны функционально.

3 голосов
/ 16 июня 2020

Следующая func перегрузка

// Denote as overload F.
template<class T1, class T2>
int func(typename id<T1>::type, typename id<T2>::type) { return 1; }

является более специализированной , чем следующая func перегрузка

// Denote as overload G.
template<class T1, class T2>
int func(T1, T2) { return 0; }

таким образом, первое выбирается по разрешению перегрузки.

(Все приведенные ниже ссылки на стандарты ISO относятся к N4659: рабочий проект, выпущенный после Kona в марте 2017 г. / DIS C ++ 17 )

Частичное упорядочение перегрузок G и F для func регулируется:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...