When we define a function template specialization, we are essentially taking over the job of the compiler. That is, we are supplying the definition to use for a specific instantiation of the original template. It is important to realize that a specialization is an instantiation; it is not an overloaded instance of the function name.
Specializations instantiate a template; they do not overload it. As a result, specializations do not affect function matching.
Whether we define a particular function as a specialization or as an independent, nontemplate function can impact function matching. For example, we have defined two versions of our compare
function template, one that takes references to array parameters and the other that takes const T&
. The fact that we also have a specialization for character pointers has no impact on function matching. When we call compare
on a string literal:
compare("hi", "mom")
both function templates are viable and provide an equally good (i.e., exact) match to the call. However, the version with character array parameters is more specialized (§ 16.3, p. 695) and is chosen for this call.
Had we defined the version of compare
that takes character pointers as a plain nontemplate function (rather than as a specialization of the template), this call would resolve differently. In this case, there would be three viable functions: the two templates and the nontemplate character-pointer version. All three are also equally good matches for this call. As we’ve seen, when a nontemplate provides an equally good match as a function template, the nontemplate is selected (§ 16.3, p. 695)
Key Concept: Ordinary Scope Rules Apply to Specializations
In order to specialize a template, a declaration for the original template must be in scope. Moreover, a declaration for a specialization must be in scope before any code uses that instantiation of the template.
With ordinary classes and functions, missing declarations are (usually) easy to find—the compiler won’t be able to process our code. However, if a specialization declaration is missing, the compiler will usually generate code using the original template. Because the compiler can often instantiate the original template when a specialization is missing, errors in declaration order between a template and its specializations are easy to make but hard to find.
It is an error for a program to use a specialization and an instantiation of the original template with the same set of template arguments. However, it is an error that the compiler is unlikely to detect.
Templates and their specializations should be declared in the same header file. Declarations for all the templates with a given name should appear first, followed by any specializations of those templates.