Partial ordering of function templates
We mentioned earlier that an ordinary function overload of min( ) is preferable to using the template. If a function already exists to match a function call, why generate another? In the absence of ordinary functions, however, it is possible that overloaded function templates can lead to ambiguities. To minimize the chances of this, an ordering is defined for function templates that chooses the
template
template
template
The first template can be matched with any type. The second template is more specialized than the first because only pointer types match it. In other words, you can look upon the set of possible calls that match the second template as a subset of the first. A similar relationship exists between the second and third template declarations above: the third can only be called for pointers to const, but the second accommodates any pointer type. The following program illustrates these rules.
//: C05:PartialOrder.cpp
// Reveals Ordering of Function Templates
#include
using namespace std;
template
void f(T) {
cout << "T\n";
}
template
void f(T*) {
cout << "T*\n";
}
template
void f(const T*) {
cout << "const T*\n";
}
int main() {
f(0); // T
int i = 0;
f(&i); // T*
const int j = 0;
f(&j); // const T*
} ///:~
The call f(&i) certainly matches the first template, but since the second is more specialized, it is called. The third can’t be called in this case since the pointer is not a pointer to const. The call f(&j) matches all three templates (for example, T would be const int in the second template), but again, the third template is more specialized, so it is used instead.
If there is no "most specialized" template among a set of overloaded function templates, an ambiguity remains and the compiler will report an error. That is why this feature is called a "partial ordering"—it may not be able to resolve all possibilities. Similar rules exist for class templates (see the section "Partial specialization" below).
Template specialization
The term
Explicit specialization
You can also provide the code yourself for a given template specialization, should the need arise. Providing your own template specializations is often needed with class templates, but we will begin with the min function template to introduce the syntax.
Recall that in MinTest.cpp earlier in this chapter we introduced the following ordinary function:
const char* min(const char* a, const char* b) {
return (strcmp(a, b) < 0) ? a : b;
}
This was so that a call to min would compare strings and not addresses. Although it would provide no advantage in this case, we could define instead a const char* specialization for min, as in the following program:.
//: C05:MinTest2.cpp
#include
#include
using std::strcmp;
using std::cout;
using std::endl;
template
return (a < b) ? a : b;
}
// An explicit specialization of the min template
template<>
const char* const& min
const char* const& b) {
return (strcmp(a, b) < 0) ? a : b;
}
int main() {
const char *s2 = "say \"Ni-!\"", *s1 = "knights who";
cout << min(s1, s2) << endl;
cout << min<>(s1, s2) << endl;
} ///:~