Partial ordering of function templates (C++)
Multiple function templates that match the argument list of a function call can be available. C++ defines a partial ordering of function templates to specify which function should be called. The ordering is partial because there can be some templates that are considered equally specialized.
The compiler chooses the most specialized function template available from the possible matches. For example, if a function template takes a type T
and another function template that takes T*
is available, the T*
version is said to be more specialized. It's preferred over the generic T
version whenever the argument is a pointer type, even though both would be allowable matches.
Use the following process to determine if one function template candidate is more specialized:
Consider two function templates,
T1
andT2
.Replace the parameters in
T1
with a hypothetical unique typeX
.With the parameter list in
T1
, see ifT2
is a valid template for that parameter list. Ignore any implicit conversions.Repeat the same process with
T1
andT2
reversed.If one template is a valid template argument list for the other template, but the converse isn't true, then that template is considered to be less specialized than the other template. If by using the previous step, both templates form valid arguments for each other, then they're considered to be equally specialized, and an ambiguous call results when you attempt to use them.
Using these rules:
A template specialization for a specific type is more specialized than one taking a generic type argument.
A template taking only
T*
is more specialized than one taking onlyT
, because a hypothetical typeX*
is a valid argument for aT
template argument, butX
isn't a valid argument for aT*
template argument.const T
is more specialized thanT
, becauseconst X
is a valid argument for aT
template argument, butX
isn't a valid argument for aconst T
template argument.const T*
is more specialized thanT*
, becauseconst X*
is a valid argument for aT*
template argument, butX*
isn't a valid argument for aconst T*
template argument.
Example
The following sample works as specified in the standard:
// partial_ordering_of_function_templates.cpp
// compile with: /EHsc
#include <iostream>
template <class T> void f(T) {
printf_s("Less specialized function called\n");
}
template <class T> void f(T*) {
printf_s("More specialized function called\n");
}
template <class T> void f(const T*) {
printf_s("Even more specialized function for const T*\n");
}
int main() {
int i =0;
const int j = 0;
int *pi = &i;
const int *cpi = &j;
f(i); // Calls less specialized function.
f(pi); // Calls more specialized function.
f(cpi); // Calls even more specialized function.
// Without partial ordering, these calls would be ambiguous.
}
Output
Less specialized function called
More specialized function called
Even more specialized function for const T*