There may be performance advantages to treating some combinations of template arguments as a special case, as in the following examples for twice. Alternatively, a template description might fail to work for a set of its possible arguments, as in the following examples for sort. Template specialization allows you to define alternative implementations for a given combination of actual template arguments. The template specialization overrides the default instantiation.
You must declare a specialization before any use of that combination of template arguments. The following examples declare specialized implementations of twice and sort.
template <> unsigned twice<unsigned>( unsigned original ); |
template <> sort<char*>(Array<char*> store); |
You can omit the template arguments if the compiler can unambiguously determine them. For example:
template <> unsigned twice(unsigned original); |
template <> sort(Array<char*> store); |
You must define all template specializations that you declare. The following examples define the functions declared in the preceding section.
template <> unsigned twice<unsigned>(unsigned original) {return original << 1;} |
#include <string.h> template <> void sort<char*>(Array<char*> store) {int num_elems = store.GetSize(); for (int i = 0; i < num_elems-1; i++) for (int j = i+1; j < num_elems; j++) if (strcmp(store[j-1], store[j]) > 0) {char *temp = store[j]; store[j] = store[j-1]; store[j-1] = temp;}} |
A specialization is used and instantiated just as any other template, except that the definition of a completely specialized template is also an instantiation.
In the previous examples, the templates are fully specialized. That is, they define an implementation for specific template arguments. A template can also be partially specialized, meaning that only some of the template parameters are specified, or that one or more parameters are limited to certain categories of type. The resulting partial specialization is itself still a template. For example, the following code sample shows a primary template and a full specialization of that template.
template<class T, class U> class A {...}; //primary template template<> class A<int, double> {...}; //specialization |
The following code shows examples of partial specialization of the primary template.
template<class U> class A<int> {...}; // Example 1 template<class T, class U> class A<T*> {...}; // Example 2 template<class T> class A<T**, char> {...}; // Example 3 |
Example 1 provides a special template definition for cases when the first template parameter is type int.
Example 2 provides a special template definition for cases when the first template parameter is any pointer type.
Example 3 provides a special template definition for cases when the first template parameter is pointer-to-pointer of any type, and the second template parameter is type char.