8.1 Parameterized Declarations

Ru-Brd

C++ currently supports two fundamental kinds of templates: class templates and function templates (see Section 13.6 on page 212 for a possible future change in this area). This classification includes member templates. Such templates are declared much like ordinary classes and functions, except for being introduced by a parameterization clause of the form

 template<  parameters here  > 

or perhaps

 export template<  parameters here  > 

(see Section 6.3 on page 68 and Section 10.3.3 on page 149 for a detailed explanation of the keyword export ).

We'll come back to the actual template parameter declarations in a later section. An example illustrates the two kinds of templates, both as class members and as ordinary namespace scope declarations:

 template <typename T>  class List {  // a namespace scope class template  public:      template <typename T2>  // a member function template  List (List<T2> const&);  // (constructor)    };  template <typename T>   template <typename T2>  List<T>::List (List<T2> const& b)  // an out-of-class member function  {  // template definition    }  template <typename T>  int length (List<T> const&);  // a namespace scope function template  class Collection {      template <typename T>  // an in-class member class template  class Node {  // definition    };      template <typename T>  // another member class template,  class Handle;  // without its definition  template <typename T>  // an in-class (and therefore implicitly  T* alloc() {  // inline) member function template   // definition  }   };  template <typename T>  // an out-of-class member class  class Collection::Node {  // template definition    }; 

Note how member templates defined outside their enclosing class can have multiple template< > parameterization clauses: one for the template itself and one for every enclosing class template. The clauses are listed starting from the outermost class template.

Union templates are possible too (and they are considered a kind of class template):

 template <typename T>  union AllocChunk {      T object;      unsigned char bytes[sizeof(T)];  }; 

Function templates can have default call arguments just like ordinary function declarations:

 template <typename T>  void report_top (Stack<T> const&, int number = 10);  template <typename T>  void fill (Array<T>*, T const& = T());  //  T()  is zero for built-in types  

The latter declaration shows that a default call argument could depend on a template parameter. When the fill() function is called, the default argument is not instantiated if a second function call argument is supplied. This ensures that no error is issued if the default call argument cannot be instantiated for a particular T . For example:

 class Value {    public:      Value(int);  // no default constructor  };  void init (Array<Value>* array)  {      Value zero(0);      fill(array, zero);  // OK:  = T()  is not used  fill(array);  // ERROR:  = T()  is used, but not valid for  T = Value  } 

In addition to the two fundamental kinds of templates, three other kinds of declarations can be parameterized using a similar notation. All three correspond to definitions of members of class templates [1] :

[1] They are much like ordinary class members, but they are occasionally (erroneously) referred to as member templates .

  1. Definitions of member functions of class templates

  2. Definitions of nested class members of class templates

  3. Definitions of static data members of class templates

Although they can be parameterized, such definitions aren't quite first-class templates. Their parameters are entirely determined by the template of which they are members. Here is an example of such definitions:

 template <int I>  class CupBoard {      void open();      class Shelf;      static double total_weight;   };  template <int I>  void CupBoard<I>::open()  {   }  template <int I>  class CupBoard<I>::Shelf {   };  template <int I>  double CupBoard<I>::total_weight = 0.0; 

Although such parameterized definitions are commonly called templates , there are contexts when the term doesn't quite apply to them.

8.1.1 Virtual Member Functions

Member function templates cannot be declared virtual. This constraint is imposed because the usual implementation of the virtual function call mechanism uses a fixed-size table with one entry per virtual function. However, the number of instantiations of a member function template is not fixed until the entire program has been translated. Hence, supporting virtual member function templates would require support for a whole new kind of mechanism in C++ compilers and linkers.

In contrast, the ordinary members of class templates can be virtual because their number is fixed when a class is instantiated:

 template <typename T>  class Dynamic {    public:      virtual ~Dynamic();  // OK: one destructor per instance of  Dynamic<T>      template <typename T2>      virtual void copy (T2 const&);  // ERROR: unknown number of instances of  copy()  //        given an instance of  Dynamic<T>  }; 

8.1.2 Linkage of Templates

Every template must have a name and that name must be unique within its scope, except that function templates can be overloaded (see Chapter 12). Note especially that, unlike class types, class templates cannot share a name with a different kind of entity:

 int C;  class C;  // OK: class names and nonclass names are in a different ''space''  int X;  template <typename T>  class X;  // ERROR: conflict with variable  X  struct S;  template <typename T>  class S;  // ERROR: conflict with  struct S 

Template names have linkage, but they cannot have C linkage . Nonstandard linkages may have an implementation-dependent meaning (however, we don't know of an implementation that supports nonstandard name linkages for templates):

 extern "C++" template <typename T>  void normal();  // this is the default: the linkage specification could be left out  extern "C" template <typename T>  void invalid();  // invalid: templates cannot have C linkage  extern "Xroma" template <typename T>  void xroma_link();  // nonstandard, but maybe some compiler will some day   // support linkage compatible with the Xroma language  

Templates usually have external linkage. The only exceptions are namespace scope function templates with the static specifier :

 template <typename T>  void external();  // refers to the same entity as a declaration of   // the same name (and scope) in another file  template <typename T>  static void internal();  // unrelated to a template with the same name in   // another file  

Note that templates cannot be declared in a function.

8.1.3 Primary Templates

Normal declarations of templates declare so-called primary templates . Such template declarations are declared without adding template arguments in angle brackets after the template name:

 template<typename T> class Box;  // OK: primary template  template<typename T> class Box<T>;  // ERROR  template<typename T> void translate(T*);  // OK: primary template  template<typename T> void translate<T>(T*);  // ERROR  

Nonprimary class templates occur when declaring so-called partial specializations which are discussed in Chapter 12. Function templates must always be primary templates (but see Section 13.7 on page 213 for a potential future language change).

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