17 Templates [temp]

17.5 Template declarations [temp.decls]

17.5.6 Function templates [temp.fct]

17.5.6.2 Partial ordering of function templates [temp.func.order]

Если шаблон функции перегружен, использование специализации шаблона функции может быть неоднозначным, поскольку template argument deduction может связать специализацию шаблона функции с более чем одним объявлением шаблона функции. Partial ordering объявлений перегруженных шаблонов функций используется в следующих контекстах для выбора шаблона функции, на который ссылается специализация шаблона функции:

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

Чтобы создать преобразованный шаблон, для каждого типа, не-типа или параметра шаблона шаблона (включая template parameter packs их) синтезируйте уникальный тип, значение или шаблон класса соответственно и заменяйте его для каждого вхождения этого параметра в типе функции шаблона. [ Note: Тип, заменяющий заполнитель в типе значения, синтезированного для параметра шаблона, не являющегося типом, также является уникальным синтезированным типом. ] Если только один из шаблонов функций является нестатическим членом некоторого класса , считается, что в его список параметров функции вставлен новый первый параметр. Принимая во внимание , как CV-классификаторов (если таковые имеются), новый параметр имеет тип «ссылки на RValue » , если по желанию из вне или , если не имеет , и первый параметр другого шаблона имеет RValue ссылочный тип. В противном случае новый параметр имеет тип «ссылка lvalue на ». [ Это позволяет упорядочивать нестатический член по отношению к функции, не являющейся членом, а результаты должны быть эквивалентны упорядочению двух эквивалентных нечленов. ] [end note M A M cv Mcv Aref-qualifierM && M ref-qualifier cv ANote: end noteExample:

struct A { };
template<class T> struct B {
  template<class R> int operator*(R&);              // #1
};

template<class T, class R> int operator*(T&, R&);   // #2

// The declaration of B​::​operator* is transformed into the equivalent of
// template<class R> int operator*(B<A>&, R&);      // #1a

int main() {
  A a;
  B<A> b;
  b * a;                                            // calls #1a
}

end example]

Используя тип функции преобразованного шаблона функции, выполните определение типа для другого шаблона, как описано в [temp.deduct.partial].

[Example:

template<class T> struct A { A(); };

template<class T> void f(T);
template<class T> void f(T*);
template<class T> void f(const T*);

template<class T> void g(T);
template<class T> void g(T&);

template<class T> void h(const T&);
template<class T> void h(A<T>&);

void m() {
  const int* p;
  f(p);             // f(const T*) is more specialized than f(T) or f(T*)
  float x;
  g(x);             // ambiguous: g(T) or g(T&)
  A<int> z;
  h(z);             // overload resolution selects h(A<T>&)
  const A<int> z2;
  h(z2);            // h(const T&) is called because h(A<T>&) is not callable
}

end example]

[ Note: Поскольку частичное упорядочение в контексте вызова учитывает только параметры, для которых есть явные аргументы вызова, некоторые параметры игнорируются (а именно, пакеты параметров функций, параметры с аргументами по умолчанию и параметры с многоточием). [Example:

template<class T> void f(T);                            // #1
template<class T> void f(T*, int=1);                    // #2
template<class T> void g(T);                            // #3
template<class T> void g(T*, ...);                      // #4
int main() {
  int* ip;
  f(ip);                                                // calls #2
  g(ip);                                                // calls #4
}

end example] [Example:

template<class T, class U> struct A { };

template<class T, class U> void f(U, A<U, T>* p = 0);   // #1
template<         class U> void f(U, A<U, U>* p = 0);   // #2
template<class T         > void g(T, T = T());          // #3
template<class T, class... U> void g(T, U ...);         // #4

void h() {
  f<int>(42, (A<int, int>*)0);                          // calls #2
  f<int>(42);                                           // error: ambiguous
  g(42);                                                // error: ambiguous
}

end example] [Example:

template<class T, class... U> void f(T, U...);          // #1
template<class T            > void f(T);                // #2
template<class T, class... U> void g(T*, U...);         // #3
template<class T            > void g(T);                // #4

void h(int i) {
  f(&i);                                                // error: ambiguous
  g(&i);                                                // OK: calls #3
}

end example] ] end note