14 Templates [temp]

14.5 Template declarations [temp.decls]

14.5.6 Function templates [temp.fct]

A function template defines an unbounded set of related functions. [ Example: a family of sort functions might be declared like this:

template<class T> class Array { };
template<class T> void sort(Array<T>&);

 — end example ]

A function template can be overloaded with other function templates and with non-template functions ([dcl.fct]). A non-template function is not related to a function template (i.e., it is never considered to be a specialization), even if it has the same name and type as a potentially generated function template specialization.141

That is, declarations of non-template functions do not merely guide overload resolution of function template specializations with the same name. If such a non-template function is odr-used ([basic.def.odr]) in a program, it must be defined; it will not be implicitly instantiated using the function template definition.

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

If a function template is overloaded, the use of a function template specialization might be ambiguous because template argument deduction ([temp.deduct]) may associate the function template specialization with more than one function template declaration. Partial ordering of overloaded function template declarations is used in the following contexts to select the function template to which a function template specialization refers:

Partial ordering selects which of two function templates is more specialized than the other by transforming each template in turn (see next paragraph) and performing template argument deduction using the function type. The deduction process determines whether one of the templates is more specialized than the other. If so, the more specialized template is the one chosen by the partial ordering process.

To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs ([temp.variadic]) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template. If only one of the function templates is a non-static member of some class A, that function template is considered to have a new first parameter inserted in its function parameter list. Given cv as the cv-qualifiers of the function template (if any), the new parameter is of type “rvalue reference to cv A” if the optional ref-qualifier of the function template is &&, or of type “lvalue reference to cv A” otherwise. [ Note: This allows a non-static member to be ordered with respect to a nonmember function and for the results to be equivalent to the ordering of two equivalent nonmembers.  — end note ] [ Example:

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 ]

Using the transformed function template's function type, perform type deduction against the other template as described in [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: Since partial ordering in a call context considers only parameters for which there are explicit call arguments, some parameters are ignored (namely, function parameter packs, parameters with default arguments, and ellipsis parameters). [ 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 ]