В разделе 2.4 Overloading Function Templates
книги «Шаблоны C ++ — Полное руководство» вы найдете следующий пример:
// maximum of two int values
inline int const& max (int const& a, int const& b)
{
return a < b ? b : a;
}
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
return max (max(a,b), c);
}
int main()
{
::max(7, 42); // calls the nontemplate for two ints (1)
}
Однако в B.2 Упрощенное разрешение перегрузки в Приложении B автор заявляет:
Обратите внимание, что разрешение перегрузки происходит после шаблон Аргумент вычета, … (2)
В соответствии с (2)
, ::max(7,42)
должен позвонить max<int>
по аргументу вычета.
После разрешения аргумента выгрузки аргумента шаблона происходит между
1) inline int const& max (int const& a, int const& b);
а также
2) template <>
inline int const& max (int const& a, int const& b)
В этой ситуации 1) вызывается так, как указано в стандарте C ++ 13.3.3 пар. 1 (Проект № 3092).
Msdn также ясно заявляет это:
Если не шаблонная функция одинаково хорошо соответствует шаблонной функции, выбирается не шаблонная функция
http://msdn.microsoft.com/en-us/library/s016dfe8%28v=vs.80%29.aspx
Компилятор предпочтет не шаблонную функцию в разрешении перегрузки, если обе функции точно совпадают, включая cv
классификаторы.
Поэтому здесь не будет выбран шаблон, даже если шаблонная функция по существу совпадает.
РЕДАКТИРОВАТЬ:
В стандартном проекте N3485 я нашел это:
13.3.3 Лучшая жизнеспособная функция [over.match.best]
Учитывая эти определения, жизнеспособная функция F1 определяется как лучше функции, чем другая жизнеспособная функция F2, если для всех аргументов i ICSi (F1) не хуже последовательности преобразования, чем ICSi (F2), а затем
…
— F1 — это не шаблонная функция и F2 — специализация шаблона функции, или, если нет,
— F1 и F2 являются специализациями шаблонов функций, а шаблон функций для F1 более специализирован, чем шаблон для F2, согласно правилам частичного упорядочения, описанным в 14.5.6.2.
…
В соответствии с
(2)
,::max(7,42)
должен позвонитьmax<int>
по аргументу вычета.
Нет. Подумайте об этом, чтобы выполнить разрешение перегрузки (иначе говоря, чтобы выбрать наилучшее соответствие), компилятору сначала нужно знать все доступные перегрузки и уметь сравнивать их. Обратите внимание, что шаблон функции сам по себе не является допустимой функцией, сначала он должен быть инстанцирован создать реальную функцию.
Это означает, что сначала компилятор присматривает за всеми именами шаблонов функций max
, пытается вывести аргументы шаблона для каждого из них, а затем выполняет разрешение перегрузки для созданных экземпляров функций вместе с не шаблонными функциями.
Вот визуализация функций (для краткости опущены cv-квалификаторы):
int max(int, int);
template<class Arg> Arg max(Arg, Arg);
template<class Arg> Arg max(Arg, Arg, Arg);
Давайте пройдемся по призыву ::max(7, 42)
,
Во-первых, компилятор видит, что есть три функции-кандидата. Тем не менее, он не может просто сравнить первую перегрузку max
с другими двумя — это было бы похоже на сравнение яблок и апельсинов. Вместо этого сначала нужно «вычеркнуть» реальную функцию из чертежей шаблона функции. В нашем случае это происходит путем вывода аргументов шаблона:
int max(int, int); // originally non-template
int max(int, int); // originally template
int max(int, int, int); // not enough arguments, invalid
С выбросом третьей перегрузки из-за несоответствия количества аргументов / параметров мы сократились до двух. С точки зрения разрешения перегрузки оба равны — но подождите! Теперь в это правило входит следующее правило:
§13.3.3 [over.match.best] p1
[…] Учитывая эти определения, жизнеспособная функцияF1
определяется как лучшая функция, чем другая жизнеспособная функцияF2
если […]:
F1
это не шаблонная функция иF2
специализация шаблона функции,
Согласно пункту 13.3.3 / 1 («Лучшая жизнеспособная функция» в контексте разрешения перегрузки) стандарта C ++ 11:
Определите ICSi (F) следующим образом:
— если F является статической функцией-членом, ICS1 (F) определяется так, что ICS1 (F) не является ни лучше, ни хуже, чем
ICS1 (G) для любой функции G и, симметрично, ICS1 (G) не лучше и не хуже, чем ICS1 (F) 132;
иначе,— пусть ICSi (F) обозначает последовательность неявного преобразования, которая преобразует i-й аргумент в списке в
тип i-го параметра жизнеспособной функции F. 13.3.3.1 определяет последовательности неявного преобразования и
13.3.3.2 определяет, что значит для одной неявной последовательности преобразования быть лучшей последовательностью преобразования
или хуже, последовательность преобразования, чем другой.Учитывая эти определения, жизнеспособная функция F1 определяется как лучшая функция, чем другая жизнеспособная функция
F2 если для всех аргументов i ICSi (F1) не хуже последовательности преобразования, чем ICSi (F2), а затем— для некоторого аргумента j ICSj (F1) является лучшей последовательностью преобразования, чем ICSj (F2), или, если не так,
— контекст является инициализацией путем пользовательского преобразования (см. 8.5, 13.3.1.5 и 13.3.1.6) и
стандартная последовательность преобразования из типа возврата F1 в тип назначения (то есть тип
инициализируемая сущность) является лучшей последовательностью преобразования, чем стандартная последовательность преобразования из
тип возврата F2 к типу назначения. […]— F1 — это не шаблонная функция, а F2 — специализация шаблонов функций., или, если не это,
— F1 и F2 являются специализациями шаблонов функций, а шаблон функций для F1 более специализирован.
чем шаблон для F2 в соответствии с правилами частичного заказа, описанными в 14.5.6.2.
Это означает, что в контексте разрешения перегрузки, когда функция, сгенерированная путем создания экземпляра шаблона функции (следовательно, после определения типа), одинаково хорошо соответствует функции, не являющейся шаблоном, предпочтительна функция без шаблона.