17 Templates [temp]

17.5 Template declarations [temp.decls]

17.5.6 Function templates [temp.fct]

17.5.6.1 Function template overloading [temp.over.link]

Можно перегрузить шаблоны функций, чтобы две разные специализации шаблонов функций имели один и тот же тип. [Example:

// translation unit 1:
template<class T>
  void f(T*);
void g(int* p) {
  f(p); // calls f<int>(int*)
}
// translation unit 2:
template<class T>
  void f(T);
void h(int* p) {
  f(p); // calls f<int*>(int*)
}

end example]

Такие специализации являются разными функциями и не нарушают one-definition rule.

Подпись шаблона функции определена в разделе [intro.defs]. Имена параметров шаблона важны только для установления связи между параметрами шаблона и остальной частью подписи. [ Note: Два разных шаблона функций могут иметь идентичные типы возвращаемых функций и списки параметров функций, даже если одно разрешение перегрузки не может их различить.

template<class T> void f();
template<int I> void f();       // OK: overloads the first template
                                // distinguishable with an explicit template argument list

end note]

Когда выражение, которое ссылается на параметр шаблона, используется в списке параметров функции или возвращаемом типе в объявлении шаблона функции, выражение, которое ссылается на параметр шаблона, является частью сигнатуры шаблона функции. Это необходимо для того, чтобы объявление шаблона функции в одной единице трансляции было связано с другим объявлением шаблона функции в другой единице трансляции и, наоборот, чтобы гарантировать, что шаблоны функций, которые должны быть различными, не связаны друг с другом. . [Example:

template <int I, int J> A<I+J> f(A<I>, A<J>);   // #1
template <int K, int L> A<K+L> f(A<K>, A<L>);   // same as #1
template <int I, int J> A<I-J> f(A<I>, A<J>);   // different from #1

end example] [ Note: Большинство выражений, использующих параметры шаблона, используют параметры шаблона, не являющиеся типами, но выражение может ссылаться на параметр типа. Например, вsizeof операторе можно использовать параметр типа шаблона . ]end note

Два выражения, включающие параметры шаблона, рассматриваются, equivalent если два определения функции, содержащие эти выражения, удовлетворяют требованиям one-definition rule, за исключением того, что токены, используемые для наименования параметров шаблона, могут отличаться до тех пор, пока токен, используемый для наименования параметра шаблона в одном выражении, заменяется другим токеном, который называет тот же параметр шаблона в другом выражении. Для определения того, dependent names являются ли два эквивалентными, учитывается только само имя, а не результат поиска имени в контексте шаблона. Если несколько объявлений одного и того же шаблона функции отличаются в результате этого поиска имени, используется результат для первого объявления. [Example:

template <int I, int J> void f(A<I+J>);         // #1
template <int K, int L> void f(A<K+L>);         // same as #1

template <class T> decltype(g(T())) h();
int g(int);
template <class T> decltype(g(T())) h()         // redeclaration of h() uses the earlier lookup
  { return g(T()); }                            // ...although the lookup here does find g(int)
int i = h<int>();                               // template argument substitution fails; g(int)
                                                // was not in scope at the first declaration of h()

end example] Два выражения, включающие параметры шаблона, которые не эквивалентны, - это functionally equivalent если для любого заданного набора аргументов шаблона результат вычисления выражения дает одно и то же значение.

Два шаблона функций - это equivalent если они объявлены в одной области действия, имеют одинаковое имя, одинаковые списки параметров шаблона и эквивалентные типы возвращаемых значений и списки параметров с использованием описанных выше правил для сравнения выражений, включающих параметры шаблона. Два шаблона функций functionally equivalent являются эквивалентными, за исключением того, что одно или несколько выражений, включающих параметры шаблона в возвращаемых типах и списках параметров, функционально эквивалентны с использованием описанных выше правил для сравнения выражений, включающих параметры шаблона. Если программа содержит объявления шаблонов функций, которые функционально эквивалентны, но не эквивалентны, это означает, что программа имеет неправильный формат, и диагностика не требуется.

[ Note: Это правило гарантирует, что эквивалентные объявления будут связаны друг с другом, при этом не требуя от реализации героических усилий, чтобы гарантировать, что функционально эквивалентные объявления будут рассматриваться как отдельные. Например, последние два объявления функционально эквивалентны и могут привести к неправильному формату программы:

// Guaranteed to be the same
template <int I> void f(A<I>, A<I+10>);
template <int I> void f(A<I>, A<I+10>);

// Guaranteed to be different
template <int I> void f(A<I>, A<I+10>);
template <int I> void f(A<I>, A<I+11>);

// Ill-formed, no diagnostic required
template <int I> void f(A<I>, A<I+10>);
template <int I> void f(A<I>, A<I+1+2+3+4>);

end note]