Ru-Brd |
5.1 Keyword typenameThe keyword typename was introduced during the standardization of C++ to clarify that an identifier inside a template is a type. Consider the following example: template <typename T> class MyClass { typename T::SubType * ptr; }; Here, the second typename is used to clarify that SubType is a type defined within class T . Thus, ptr is a pointer to the type T::SubType . Without typename , SubType would be considered a static member. Thus, it would be a concrete variable or object. As a result, the expression T::SubType * ptr would be a multiplication of the static SubType member of class T with ptr . In general, typename has to be used whenever a name that depends on a template parameter is a type. This is discussed in detail in Section 9.3.2 on page 130. A typical application of typename is the access to iterators of STL containers in template code: // basics/printcoll.hpp #include <iostream> // print elements of an STL container template <typename T> void printcoll (T const& coll) { typename T::const_iterator pos; // iterator to iterate over coll typename T::const_iterator end(coll.end()); // end position for (pos=coll.begin(); pos!=end; ++pos) { std::cout << *pos << ' '; } std::cout << std::endl; } In this function template, the call parameter is an STL container of type T . To iterate over all elements of the container, the iterator type of the container is used, which is declared as type const_iterator inside each STL container class: class stlcontainer { typedef iterator; // iterator for read/write access typedef const_iterator; // iterator for read access }; Thus, to access type const_iterator of template type T , you have to qualify it with a leading typename : typename T::const_iterator pos; The .template ConstructA very similar problem was discovered after the introduction of typename . Consider the following example using the standard bitset type: template<int N> void printBitset (std::bitset<N> const& bs) { std::cout << bs.template to_string<char,char_traits<char>, allocator<char> >(); } The strange construct in this example is .template . Without that extra use of template , the compiler does not know that the less-than token ( < ) that follows is not really "less than" but the beginning of a template argument list. Note that this is a problem only if the construct before the period depends on a template parameter. In our example, the parameter bs depends on the template parameter N . In conclusion, the .template notation (and similar notations such as ->template ) should be used only inside templates and only if they follow something that depends on a template parameter. See Section 9.3.3 on page 132 for details. |
Ru-Brd |