DekGenius.com
Team LiB   Previous Section   Next Section

7.2 Template Declarations

A template declaration begins with a template header followed by a function declaration or definition, or a class declaration or definition. Template declarations can appear only at namespace or class scope. The template name must be unique in its scope (except for overloaded functions).

The template header starts with the template keyword followed by the template parameters enclosed in angle brackets (<>). Multiple parameters are separated by commas. The syntax is:

template < parameter-list > declaration

There are three kinds of template parameters: values, types, and class templates. Similar to a function parameter, a template parameter has an optional name and an optional default argument.

Function templates cannot have default template arguments. If a class template has member definitions that are outside the class definition, only the class template takes default arguments; the individual member definitions do not. If a default argument is present, it is preceded by an equal sign. Only the rightmost parameters can have default arguments. If any parameter has a default argument, all parameters to its right must also have default arguments. Example 7-2 shows valid and invalid member definitions.

Example 7-2. Defining members of a class template
// OK: default argument for template parameter A
template<typename T, typename A = std::allocator<T> >
class hashset {
  bool empty(  ) const;
  size_t size(  ) const;
  ...
};
// Error: do not use default argument here
template<typename T, typename A = std::allocator<T> >
bool hashset<T,A>::empty(  ) { return size(  ) == 0; }

// OK
template<typename T, typename A>
size_t hashset<T,A>::size(  ) { ... }

Each template header defines the template name and template parameters. The scope of a parameter name extends from its declaration to the end of the declaration or definition of the class or function. A parameter name can be used in subsequent template parameters in the same template header (such as std::allocator<T> in Example 7-2). The template parameter name must be unique in the template declaration and cannot be redeclared in its scope. If a class template has separate definitions for its members, each member definition is free to use different names for the template parameters. (See Section 7.4.1 later in this chapter for more information.)

There are three kinds of template parameters:

Value template parameter

Declared in the same manner as a function parameter:

type-specifiers declarator
type-specifiers declarator = expr

The type must be an integral, enumeration, pointer, reference, or pointer-to-member type. When the template is instantiated, the argument must be a constant integral or enumeration expression, the address of a named object or function with external linkage, or the address of a member:

template<unsigned Size>
struct name {
  // ...
  unsigned size(  ) const { return Size; }
private:
  char name_[Size+1];
};
name<100> n;

Note that a string literal is an unnamed object with internal linkage, so you cannot use it as a template argument:

template<const char* Str> void print(const char* s = Str);
print<"default">(  ); // Error
const char def[] = "default";
print<def>(  );       // OK

The type-specifiers can be elaborated type specifiers that start with typename, that is, typename followed by a qualified type name. (If typename is followed by a plain identifier, the template parameter is a type parameter, as described later.) For more information about this use of typename, see Section 7.8 later in this chapter.

template<typename list<int>::value_type value>
int silly(  ) { return value; }
Type template parameter

Introduced with the keyword typename followed by the optional parameter name:

typename identifier
typename identifier = type

The class keyword can be used in place of typename and has the same meaning in this context. (A useful convention is to use class when the argument must be a class and typename when the argument can be any type.) When the template is instantiated, the argument must be a type (that is, a list of type specifiers with optional pointer, reference, array, and function operators). In the following example, the point template is instantiated with unsigned long int as the template argument:

template<typename T> struct point {
  T x, y;
};
point<unsigned long int> pt;

If typename is followed by a qualified type name instead of a plain identifier, it declares a value parameter of that type, as described earlier.

Template template parameter

Must be a class template. It has the form of a template declaration:

template < parameter-list > class identifier
template < parameter-list > class identifier = template-id

When the template is instantiated, the argument must be a class template:

// Erase all occurrences of item from a sequence container.
template<template<typename T, typename A> class C, typename T, 
         typename A>
void erase(C<T,A>& c, const T& item)
{
  c.erase(std::remove(c.begin(), c.end(  ), item), c.end(  ));
}
...
list<int> l;
...
erase(l, 42);

To use a template declaration, you must create an instance of the template, either explicitly (by naming the template and enclosing a list of template arguments in angle brackets) or implicitly (by letting the compiler deduce the template arguments from context) for a function template. In either case, the compiler must know about a template declaration before the template is used. Typically, a template is declared in an #include file or header. The header declares the function or class template and possibly provides the definition of the function template or the definitions of all the members of the class template. See Section 7.10 later in this chapter for details about the files that declare and define templates.

A template instance must provide an argument for each template parameter. If a class template has fewer arguments than parameters, the remaining parameters must have default arguments, which are used for the template instance.

If a function template has fewer arguments than parameters, the remaining arguments are deduced from the context of the function call (as explained in the next section). If the arguments cannot be deduced, the compiler reports an error. See Section 7.7 later in this chapter for more information.

    Team LiB   Previous Section   Next Section