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:
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; }
Introduced with the keyword typename
followed by the optional
parameter name:
typenameidentifier
typenameidentifier
=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.
Must be a class template. It has the form of a template declaration:
template <parameter-list
> classidentifier
template <parameter-list
> classidentifier
=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.