|
C++ Templates Authors: Vandevoorde D., Josuttis N.M. Published year: 2002 Pages: 35-37/185 |
| Ru-Brd |
4.4 Summary
|
| Ru-Brd |
| Ru-Brd |
Chapter 5. Tricky BasicsThis chapter covers some further basic aspects of templates that are relevant to the practical use of templates: an additional use of the typename keyword, defining member functions and nested classes as templates, template template parameters, zero initialization, and some details about using string literals as arguments for function templates. These aspects can be tricky at times, but every day-to-day programmer should have heard of them. |
| Ru-Brd |
| 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 |
|
C++ Templates Authors: Vandevoorde D., Josuttis N.M. Published year: 2002 Pages: 35-37/185 |