3.3 Specializations of Class Templates

Ru-Brd

You can specialize a class template for certain template arguments. Similar to the overloading of function templates (see page 15), specializing class templates allows you to optimize implementations for certain types or to fix a misbehavior of certain types for an instantiation of the class template. However, if you specialize a class template, you must also specialize all member functions. Although it is possible to specialize a single member function, once you have done so, you can no longer specialize the whole class.

To specialize a class template, you have to declare the class with a leading template<> and a specification of the types for which the class template is specialized. The types are used as a template argument and must be specified directly following the name of the class:

 template<>  class Stack<std::string> {   }; 

For these specializations, any definition of a member function must be defined as an "ordinary" member function, with each occurrence of T being replaced by the specialized type:

 void Stack<std::string>::push (std::string const& elem)  {      elems.push_back(elem);  // append copy of passed  elem  } 

Here is a complete example of a specialization of Stack<> for type std::string:

  // basics/stack2.hpp  #include <deque>  #include <string>  #include <stdexcept>  #include "stack1.hpp"  template<>  class Stack<std::string> {    private:      std::deque<std::string> elems;  // elements  public:      void push(std::string const&);  // push element  void pop();  // pop element  std::string top() const;  // return top element  bool empty() const {  // return whether the stack is empty  return elems.empty();      }  };  void Stack<std::string>::push (std::string const& elem)  {      elems.push_back(elem);  // append copy of passed  elem  }  void Stack<std::string>::pop ()  {      if (elems.empty()) {          throw std::out_of_range                  ("Stack<std::string>::pop(): empty stack");      }      elems.pop_back();  // remove last element  }  std::string Stack<std::string>::top () const  {      if (elems.empty()) {          throw std::out_of_range                  ("Stack<std::string>::top(): empty stack");      }      return elems.back();  // return copy of last element  } 

In this example, a deque instead of a vector is used to manage the elements inside the stack. Although this has no particular benefit here, it does demonstrate that the implementation of a specialization might look very different from the implementation of the primary template. [2]

[2] In fact, there is a benefit for using a deque instead of a vector to implement a stack: A deque frees memory when elements are removed, and it can't happen that elements have to be moved as a result of reallocation. However, this is no particular benefit for strings. For this reason it is probably a good idea to use a deque in the primary class template (as is the case in class std::stack<> of the C++ standard library).

Ru-Brd


C++ Templates
C++ Templates: The Complete Guide
ISBN: 0201734842
EAN: 2147483647
Year: 2002
Pages: 185

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