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] :
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 FunctionsMember 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 TemplatesEvery 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 TemplatesNormal 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 |