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.