An explicit specialization is a definition for a particular type or types that is to be used instead of the general template. Sometimes you might need or want to modify a template to behave differently when instantiated for a particular type; in that case, you can create an explicit specialization. Suppose, for example, that you’ve defined a template for a class that represents a sorted array for which items are sorted as they are added to the array:

template

class SortedArray

{

     ...// details omitted

};

Also suppose the template uses the > operator to compare values. This works well for numbers. It will work if T represents a class type, too, provided that you’ve defined a T::operator>() method. But it won’t work if T is a string represented by type const char *. Actually, the template will work, but the strings will wind up sorted by address rather than alphabetically. What is needed is a class definition that uses strcmp() instead of >. In such a case, you can provide an explicit template specialization. This takes the form of a template defined for one specific type instead of for a general type. When faced with the choice of a specialized template and a general template that both match an instantiation request, the compiler uses the specialized version.

A specialized class template definition has the following form:

template <> class Classname<specialized-type-name> { ... };

Older compilers may only recognize the older form, which dispenses with the template <> prefix:

class Classname<specialized-type-name> { ... };

To provide a SortedArray template specialized for the const char * type, using the current notation, you would use code like the following:

template <> class SortedArray

{

     ...// details omitted

};

Here the implementation code would use strcmp() instead of > to compare array values. Now, requests for a SortedArray template of const char * will use this specialized definition instead of the more general template definition:

SortedArray scores;          // use general definition

SortedArray dates;  // use specialized definition

Partial Specializations

C++ allows for partial specializations, which partially restrict the generality of a template. For example, a partial specialization can provide a specific type for one of the type parameters:

// general template

    template class Pair {...};

// specialization with T2 set to int

    template class Pair {...};

The <> following the keyword template declares the type parameters that are still unspecialized. So the second declaration specializes T2 to int but leaves T1 open. Note that specifying all the types leads to an empty bracket pair and a complete explicit specialization:

// specialization with T1 and T2 set to int

    template <> class Pair {...};

The compiler uses the most specialized template if there is a choice. Here’s what would happen given the preceding three templates:

Pair p1; // use general Pair template

Pair p2;    // use Pair partial specialization

Pair p3;       // use Pair explicit specialization

Or you can partially specialize an existing template by providing a special version for pointers:

template        // general version

class Feeb { ... };

template       // pointer partial specialization

class Feeb { ... };      // modified code

If you provide a non-pointer type, the compiler uses the general version; if you provide a pointer, the compiler uses the pointer specialization:

Feeb fb1;          // use general Feeb template, T is char

Feeb fb2;        // use Feeb T* specialization, T is char

Without the partial specialization, the second declaration would use the general template, interpreting T as type char *. With the partial specialization, it uses the specialized template, interpreting T as char.

The partial specialization feature allows for making a variety of restrictions. For example, you can use the following:

// general template

    template class Trio{...};

// specialization with T3 set to T2

    template class Trio {...};

// specialization with T3 and T2 set to T1*

    template class Trio {...};

Given these declarations, the compiler would make the following choices:

Trio t1; // use general template

Trio t2; // use Trio

Trio t3; use Trio

Member Templates

A template can be a member of a structure, class, or template class. The STL requires this feature to fully implement its design. Listing 14.20 provides a short example of a template class with a nested template class and a template function as members.

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги