17 Templates [temp]

17.8 Function template specializations [temp.fct.spec]

17.8.1 Explicit template argument specification [temp.arg.explicit]

Template arguments can be specified when referring to a function template specialization by qualifying the function template name with the list of template-arguments in the same way as template-arguments are specified in uses of a class template specialization.
[Example
:
template<class T> void sort(Array<T>& v);
void f(Array<dcomplex>& cv, Array<int>& ci) {
  sort<dcomplex>(cv);                   // sort(Array<dcomplex>&)
  sort<int>(ci);                        // sort(Array<int>&)
}
and
template<class U, class V> U convert(V v);

void g(double d) {
  int i = convert<int,double>(d);       // int convert(double)
  char c = convert<char,double>(d);     // char convert(double)
}
end example
]
A template argument list may be specified when referring to a specialization of a function template
  • when a function is called,
  • when the address of a function is taken, when a function initializes a reference to function, or when a pointer to member function is formed,
  • in an explicit specialization,
  • in an explicit instantiation, or
  • in a friend declaration.
Trailing template arguments that can be deduced ([temp.deduct]) or obtained from default template-arguments may be omitted from the list of explicit template-arguments.
A trailing template parameter pack ([temp.variadic]) not otherwise deduced will be deduced to an empty sequence of template arguments.
If all of the template arguments can be deduced, they may all be omitted; in this case, the empty template argument list <> itself may also be omitted.
In contexts where deduction is done and fails, or in contexts where deduction is not done, if a template argument list is specified and it, along with any default template arguments, identifies a single function template specialization, then the template-id is an lvalue for the function template specialization.
[Example
:
template<class X, class Y> X f(Y);
template<class X, class Y, class ... Z> X g(Y);
void h() {
  int i = f<int>(5.6);          // Y is deduced to be double
  int j = f(5.6);               // ill-formed: X cannot be deduced
  f<void>(f<int, bool>);        // Y for outer f deduced to be int (*)(bool)
  f<void>(f<int>);              // ill-formed: f<int> does not denote a single function template specialization
  int k = g<int>(5.6);          // Y is deduced to be double, Z is deduced to an empty sequence
  f<void>(g<int, bool>);        // Y for outer f is deduced to be int (*)(bool),
                                // Z is deduced to an empty sequence
}
end example
]
[Note
:
An empty template argument list can be used to indicate that a given use refers to a specialization of a function template even when a non-template function ([dcl.fct]) is visible that would otherwise be used.
For example:
template <class T> int f(T);    // #1
int f(int);                     // #2
int k = f(1);                   // uses #2
int l = f<>(1);                 // uses #1
end note
]
Template arguments that are present shall be specified in the declaration order of their corresponding template-parameters.
The template argument list shall not specify more template-arguments than there are corresponding template-parameters unless one of the template-parameters is a template parameter pack.
[Example
:
template<class X, class Y, class Z> X f(Y,Z);
template<class ... Args> void f2();
void g() {
  f<int,const char*,double>("aa",3.0);
  f<int,const char*>("aa",3.0); // Z is deduced to be double
  f<int>("aa",3.0);             // Y is deduced to be const char*, and Z is deduced to be double
  f("aa",3.0);                  // error: X cannot be deduced
  f2<char, short, int, long>(); // OK
}
end example
]
Implicit conversions (Clause [conv]) will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter type contains no template-parameters that participate in template argument deduction.
[Note
:
Template parameters do not participate in template argument deduction if they are explicitly specified.
For example,
template<class T> void f(T);

class Complex {
  Complex(double);
};

void g() {
  f<Complex>(1);    // OK, means f<Complex>(Complex(1))
}
end note
]
[Note
:
Because the explicit template argument list follows the function template name, and because conversion member function templates and constructor member function templates are called without using a function name, there is no way to provide an explicit template argument list for these function templates.
end note
]
[Note
:
For simple function names, argument dependent lookup ([basic.lookup.argdep]) applies even when the function name is not visible within the scope of the call.
This is because the call still has the syntactic form of a function call ([basic.lookup.unqual]).
But when a function template with explicit template arguments is used, the call does not have the correct syntactic form unless there is a function template with that name visible at the point of the call.
If no such name is visible, the call is not syntactically well-formed and argument-dependent lookup does not apply.
If some such name is visible, argument dependent lookup applies and additional function templates may be found in other namespaces.
[Example
:
namespace A {
  struct B { };
  template<int X> void f(B);
}
namespace C {
  template<class T> void f(T t);
}
void g(A::B b) {
  f<3>(b);          // ill-formed: not a function call
  A::f<3>(b);       // well-formed
  C::f<3>(b);       // ill-formed; argument dependent lookup applies only to unqualified names
  using C::f;
  f<3>(b);          // well-formed because C​::​f is visible; then A​::​f is found by argument dependent lookup
}
end example
]
end note
]
Template argument deduction can extend the sequence of template arguments corresponding to a template parameter pack, even when the sequence contains explicitly specified template arguments.
[Example
:
template<class ... Types> void f(Types ... values);

void g() {
  f<int*, float*>(0, 0, 0);     // Types is deduced to the sequence int*, float*, int
}
end example
]