24.8 Advanced Features

I l @ ve RuBoard

There are a few advanced template features that are beyond the scope of this book. These include default parameters and partial specialization.

24.8.1 Default Parameters

Let's suppose that we wish to create a class to hold an address list. There are several different classes that hold addresses. There's one for a local addresses and one for international addresses. Since the two will never be mixed, let's use a template for our address list that handles everything:

 // Half designed template<class address> class address_list { ... } 

But there's another design feature we must consider. Some lists are short (0-1000 names) and some are long (1,000-10,000,000 names ). The short ones we can keep in memory; the long ones need to be put on disk.

There are two classes for the storing of list data, the in_memory_list and the on_disk_list . We can augment our template to include a provision for how the list is implemented:

 // Closer template<class address, class list> class address_list { .... } 

But 99% of the time we want to use the in_memory_list implementation. We can tell C++ to use this as the default in our template specification:

 // Closer template<class address, class list = in_memory_class>  class address_list { .... } 

Now if we don't specify an implementation for our list, C++ will use the in_memory_list . So the following two statements are equivalent:

 template<local_address, in_memory_class> small_local_addresses; template<local_address> small_local_addresses; 

24.8.2 Partial Specialization

When we defined our template for the function max we had to define a specialization for the case when a character pointer ( char * ) was used. Let's suppose we have a template that takes two types:

 // Template definition template<typename container, typename item> class store {...}; 

The first type is an ordered container, such as a queue or stack, and the second type is what to put in the container.

But C-style strings are a problem. They don't handle their own memory allocation, so they can be a bit tricky. What we'd like to do is to turn the C-style strings into C++ strings whenever they are used for the item .

For that we need to create a specialization of the template. But the template takes two parameters, a container and an item. If we wanted to use full specializations, we would have to create one every possible container type.

A solution is to create a partial specialization, where we specialize only the parts of the template that we need. The partial specialization for our store class looks like this:

 // Partial specilization template<typename container> class store<container, char *> {...} 

The second definition tells C++ that whenever the second parameter is a C-style sting, it should use this definition for the template. For all other types, the first definition is used.

There are a number of tricky ways partial specialization can be used. Let's look at the template:

 template<typename T1, typename T2> class example {....}; 

We can have a specialization for when the two types are the same:

 template<typename T1> class example<T1, T1> {....}; 

We can also have a different specialization for when the first parameter is a pointer:

 template<typename T1, typename T2> class example<T1*, T2> {....}; 

And so on.

Template specifications should be written with the most general first and the most specific last. That's because the compiler goes through the various forms of the template from the last declared to the first declared to see if it can find one that matches the parameters presented.

Templates are an extremely powerful programming tool. Careful planning and design is essential to using partial specialization properly. (Don't use it to patch up a bad design.)

I l @ ve RuBoard


Practical C++ Programming
Practical C Programming, 3rd Edition
ISBN: 1565923065
EAN: 2147483647
Year: 2003
Pages: 364

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net