Tricky basics


Dependent name


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;



Using this


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()
};



Template template parameters



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 it in the following simplified form:


std::stack< int, std::vector> vstack;


To provide it, 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.



Explicit call of default constructor


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;
};



Explicit Template Instantiation


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



Mixins


This is mixin as Jannis Smaragdakis calls it.


// Mixin

template <class Base>
class Mixin : public Base  { ... };

class Base { ... };



The interesting thing is, that in normal object-oriented style base is
always implemented before derived. Here we can implement inheritance
delaying the definition of the base.


//
//  suppose Graph has succ_node() and succ_edge()
//
template <class Graph>
class Counting : public Graph
{
public:
    Counting() : nodes_visited(0), edges_visited(0)  { }
    node succ_node( node v)
    {
        ++nodes_visited;
        return Graph::succ_node(v);
    }
    node succ_edge( node v)
    {
        ++edges_visited;
        return Graph::succ_edge(v);
    }
private:
    int nodes_visited;
    int edges_visited;
};

Counting< Ugraph >  counted_ugraph;
Counting< Dgraph >  counted_dgraph;



Mixin issues


Be care with the lazy instantiation:


//
//  be care with lazy instantiation
//
template <class Sortable>
class WontWork : public Sortable
{
public:
    void sort(X x)
    {
        Sortable::srot(x);  // !!misspelled
    }
};

WontWork w;


If the client never calls w.sort there is no error message!



Liskov substitutional principle


In 1977 Barbara Liskov defined her substitutional principle: an object
from the subtype can appear in every place where its supertype's objects
can. That is one of the most fundamental rule in object-orientation:
a derived object can appear everywhere the base object can.


The problem is, that this does not hold for mixins.


lass Base { ... };
class Derived : public base { ... };

template <class T> class Mixin : public T { ... };

Base        b;
Derived     d;

Mixin<Base>     mb;
Mixin<Derived>  md;

b  = d      // OK
mb = md;    // Error!




The Curiously Recurring Template Pattern (CRTP)



// The Curiously Recurring Template Pattern (CRTP)
template <typename T>
struct Base
{
    // ...
};
struct Derived : Base<Derived>
{
    // ...
};



Static polymorphism


template <class Derived>
struct base
{
    void interface()
    {
         // ...
         static_cast<Derived*>(this)->implementation();
         // ...
    }
};
 
struct derived : base<derived>
{
     void implementation();
};