8.2 Template Parameters

Ru-Brd

There are three kinds of template parameters:

  1. Type parameters (these are by far the most common)

  2. Nontype parameters

  3. Template template parameters

Template parameters are declared in the introductory parameterization clause of a template declaration. Such declarations do not necessarily need to be named:

 template <typename, int>  class X; 

A parameter name is, of course, required if the parameter is referred to later in the template. Note also that a template parameter name can be referred to in a subsequent parameter declaration (but not before):

 template <typename T,  // the first parameter is used in the  T* Root,  // declaration of the second one and  template<T*> class Buf>  // the third one  class Structure; 

8.2.1 Type Parameters

Type parameters are introduced with either the keyword typename or the keyword class : The two are entirely equivalent. [2] The keyword must be followed by a simple identifier and that identifier must be followed by a comma to denote the start of the next parameter declaration, a closing angle bracket ( > ) to denote the end of the parameterization clause, or an equal sign ( = ) to denote the beginning of a default template argument.

[2] The keyword class does not imply that the substituting argument should be a class type. It could be almost any accessible type. However, class types that are defined in a function ( local classes ) cannot be used as template arguments (independent of whether the parameter was declared with typename or class ).

Within a template declaration, a type parameter acts much like a typedef name . For example, it is not possible to use an elaborated name of the form class T when T is a template parameter, even if T were to be substituted by a class type:

 template <typename Allocator>  class List {      class Allocator* allocator;  // ERROR  friend class Allocator;  // ERROR    }; 

It is possible that a mechanism to enable such a friend declaration will be added in the future.

8.2.2 Nontype Parameters

Nontype template parameters stand for constant values that can be determined at compile or link time. [3] The type of such a parameter (in other words, the type of the value for which it stands) must be one of the following:

[3] Template template parameters do not denote types either; however, they are not considered when talking about nontype parameters.

  • An integer type or an enumeration type

  • A pointer type (including regular object pointer types, function pointer types, and pointer-to-member types)

  • A reference type (both references to objects and references to functions are acceptable)

All other types are currently excluded (although floating-point types may be added in the future, see Section 13.4 on page 210).

Perhaps surprisingly, the declaration of a nontype template parameter can in some cases also start with the keyword typename :

 template<typename T,  // a type parameter  typename T::Allocator* Allocator>  // a nontype parameter  class List; 

The two cases are easily distinguished because the first is followed by a simple identifier, whereas the second is followed by a qualified name (in other words, a name containing a double colon , :: ). Section 1.1 on page 43 and Section 9.3.2 on page 130 explain the need for the keyword typename in the nontype parameter.

Function and array types can be specified, but they are implicitly adjusted to the pointer type to which they decay:

 template<int buf[5]> class Lexer;  //  buf  is really an  int*  template<int* buf> class Lexer;  // OK: this is a redeclaration  

Nontype template parameters are declared much like variables , but they cannot have nontype specifiers like static , mutable , and so forth. They can have const and volatile qualifiers, but if such a qualifier appears at the outermost level of the parameter type, it is simply ignored:

 template<int const length> class Buffer;  //  const  is useless here  template<int length> class Buffer;  // same as previous declaration  

Finally, nontype parameters are always rvalues : Their address cannot be taken, and they cannot be assigned to.

8.2.3 Template Template Parameters

Template template parameters are placeholders for class templates. They are declared much like class templates, but the keywords struct and union cannot be used:

 template <template<typename X> class C>  // OK  void f(C<int>* p);  template <template<typename X> struct C>  // ERROR:  struct  not valid here  void f(C<int>* p);  template <template<typename X> union C>  // ERROR:  union  not valid here  void f(C<int>* p); 

In the scope of their declaration, template template parameters are used just like other class templates.

The parameters of template template parameters can have default template arguments. These default arguments apply when the corresponding parameters are not specified in uses of the template template parameter:

 template <template<typename T,                     typename A = MyAllocator> class Container>  class Adaptation {      Container<int> storage;  // implicitly equivalent to   //  Container<T, MyAllocator>   }; 

The name of a template parameter of a template template parameter can be used only in the declaration of other parameters of that template template parameter. The following contrived template illustrates this concept:

 template <template<typename T, T*> class Buf>  class Lexer {      static char storage[5];      Buf<char, &Lexer<Buf>::storage> buf;   };  template <template<typename T> class List>  class Node {      static T* storage;  // ERROR: a parameter of a template template   //        parameter cannot be used here    }; 

Usually however, the names of the template parameters of a template template parameter are not used. As a result, the former parameters are often left unnamed altogether. For example, our earlier Adaptation template could be declared as follows :

 template <template <typename,                      typename = MyAllocator> class Container>  class Adaptation  {      Container<int> storage;  // implicitly equivalent to   //  Container<int, MyAllocator>   }; 

8.2.4 Default Template Arguments

Currently, only class template declarations can have default template arguments (see Section 13.3 on page 207 for likely changes in this area). Any kind of template parameter can be equipped with a default argument, although it must match the corresponding parameter. Clearly, a default argument should not depend on its own parameter. However, it may depend on previous parameters:

 template <typename T, typename Allocator = allocator<T> >  class List; 

Similar to default function call arguments, a template parameter can have a default template argument only if default arguments were also supplied for the subsequent parameters. The subsequent default values are usually provided in the same template declaration, but they could also have been declared in a previous declaration of that template. The following example makes this clear:

 template <typename T1, typename T2, typename T3,            typename T4 = char, typename T5 = char>  class Quintuple;  // OK  template <typename T1, typename T2, typename T3 = char,            typename T4, typename T5>  class Quintuple;  // OK:  T4  and  T5  already have defaults  template <typename T1 = char, typename T2, typename T3,            typename T4, typename T5>  class Quintuple;  // ERROR:  T1  cannot have a default argument   // because  T2  doesn't have a default  

Default template arguments cannot be repeated:

 template<typename T = void>  class Value;  template<typename T = void>  class Value;  // ERROR: repeated default argument  
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