The keyword typename was introduced into C++ during the standardization to clarify that an identifier inside a template is a type (or not).
template <typename T> class MyClass { typename T::SubType * ptr; //... };
Without the typename, the name SubType would be considered as a static member. Thus it would be a concrete variable or object. As a result, the expression:
T::SubType * ptr
would be a multiplication.
In general, typename has to be used whenever a name depends on a template type.
There is may apperance of this situation in STL, like:
typename T::const_iterator pos;
For class templates with base classes, using a name x by itself is not always equivalent to this->x, even though a member x is inherited:
template <typename T> class Base { public: void bar(); }; template <typename T> class Derived : public Base<T> { public: void foo() { bar(); } // calls external bar() or error !! };
To solve this problem, use:
template <typename T> class Derived : public Base<T> { public: void foo() { this->bar(); } // or Base<T>::bar() };
Class members can also be templates. This is possible for both nested classes and member functions.
template<class T> class auto_ptr { private: T* ap; // refers to the actual owned object (if any) public: typedef T element_type; // constructor explicit auto_ptr (T* ptr = 0) throw() : ap(ptr) { } // copy constructors (with implicit conversion) // - note: nonconstant parameter auto_ptr (auto_ptr& rhs) throw() : ap(rhs.release()) { } template<class Y> auto_ptr (auto_ptr<Y>& rhs) throw() : ap(rhs.release()) { } // assignments (with implicit conversion) // - note: nonconstant parameter auto_ptr& operator= (auto_ptr& rhs) throw() { reset(rhs.release()); return *this; } template<class Y> auto_ptr& operator= (auto_ptr<Y>& rhs) throw() { reset(rhs.release()); return *this; } // ...
You can also define the templated constructor outside of the class template body:
template<class T> template<class Y> auto_ptr<T>::auto_ptr(auto_ptr<Y>& rhs) throw() : ap(rhs.release()) { } template<class T> template<class Y> auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<Y>& rhs) throw() { reset(rhs.release()); return *this; }
It can be usefull to allow a template parameter itself to be a class template.
std::stack< int, std::vector<int> > vstack;
It would be nice to write this in the following simplified form:
std::stack< int, std::vector> vstack;
To provide this, let us define the stack in the following way:
template <typename T, template <typename ELEM> class CONT = std::deque> class stack { protected: CONT<T> c; //... };
What is the difference? In the second form, the second template parameter is declared as being a class template. The default value has changed from std::deque<T> to std::deque. This parameter has to be a class template, which is instantiated for the type that is passed as the first template parameter.
The fundamental types, like int, double, etc. has no default constructor. To ensure initialization of such values as template parameters, we can use the explicit call of constructor.
template<typename T> void foo() { T x = T(); // ... }
To make sure, that this happens with the subobjects to, you should use the initializer list of the constructor:
template<typename T> class MyClass { public: MyClass() : x() {} private: T x; };
Templates are instantiated in a lazy way: only those fnctions will be generated which are eplicitelly called.
This default rule can be overruled be the explicite instantiation.
template<typename T> void print(const T& ) { ... } template<typename T> class MyClass { // ... }; template void print<int>(const int &); // generate print<int> template MyClass<double>::MyClass(); // generate constructor template class MyClass<long>; // generate the whole class