Учитывая этот код:
template <class T>
void f(T p) { //(1)
cout << "Second" << endl;
}
template <>
void f(int *p) { //(2)
cout << "Third" << endl;
}template <class T>
void f(T* p) { //(3)
cout << "First" << endl;
}
Вызов, такой как int *p; f(p);
будет выводить First
,
Если порядок объявлений изменился, вот так:
template <class T>
void f(T* p) { //(3)
cout << "First" << endl;
}template <class T>
void f(T p) { //(1)
cout << "Second" << endl;
}
template <>
void f(int *p) { //(2)
cout << "Third" << endl;
}
тот же звонок (int *p; f(p);
) будет выводить Third
,
Я читал о том, как происходит разрешение перегрузки шаблона функции: сначала разрешение учитывает только нетабличные функции и базовые базовые шаблоны. После выбора «наиболее специализированной», если она является шаблонной функцией и имеет специализацию для параметров, которые были выведены (или явно указаны), вызывается эта специализация.
Теперь мой вопрос: как это решается, для чего базовый базовый шаблон функция это специализация? В моем примере, для какой функции шаблон перегрузки ((1) или (3)) является (2) специализацией?
Я предполагаю, что когда объявляется специализация, учитываются уже объявленные шаблоны и из них выбирается наиболее «специализированный» (параметры которого «наиболее близки» к этой специализации). Это правильно? Кроме того, не могли бы вы указать мне, где это указано в стандарте?
Он печатает «Первый», потому что порядок объявления влияет на то, какой шаблон вы на самом деле специализируете.
В вашем примере есть два шаблона функций, которые перегружают одно и то же имя. В первом случае вы специализируетесь void f(T p)
, потому что это единственный шаблон, увиденный до сих пор.
Во втором случае это void f(T* p)
это специализировано. Так что да, ваше предположение верно. Специфика в [Temp.deduct.decl / 1]:
В объявлении, идентификатор объявления которого относится к специализации
шаблон функции, вывод аргумента шаблона выполняется для
определить специализацию, к которой относится декларация.
В частности, это сделано для явные экземпляры, явный
специализаций, и определенные заявления друзей. […]
И это включает частичное упорядочение шаблонов функций. Однако частичное упорядочение применяется только к объявлениям доступных шаблонов функций в том месте, где вы вводите свою специализацию.
И стандарт предупреждает в [Temp.expl.spec / 7]:
Размещение явных объявлений специализации для шаблонов функций, […], может повлиять на то, является ли программа правильно сформированной
в соответствии с относительным положением явной специализации
объявления и их пункты в модуле перевода
как указано выше и ниже. При написании специализации, будь
заботиться о его местонахождении; или сделать его компиляцией будет такое испытание
как разжечь его самосожжение.
Других решений пока нет …