Tuesday, May 25, 2010

C++ template tricks

Here are a few tricks for future reference:

1. Explicitly specify which template function version you want to call. This is especially useful if you have parameter type in return type.
template <class RET, class T>
    RET f(T t)
{
}

char ch=f<char>("abc"); //partial specify is enough as the second parameter can be deducted

 2. exported keyword is supposed to allow the template definition to be separated with the declaration. Since no one wants to support it, it is removed from C++ 0x.

In order to separate the template declaration and non-inline member function definition, you may have to put the instantiation declaration in its cpp file:

template class Foo<int>; 

3.   Friend function link error
If you declare a friend function in a template class, the compiler normally will take it as non-template definition:
Foo<int> operator+ <Foo<int>&, Foo<int>&);

In order to tell the compiler you want to use the template version:
template<class T> class Foo; //pre-declare Foo
template<class T> Foo<T> operator+(Foo<T>&, Foo<T>&); //a template declaration for friend

template <class T> class Foo{
//...
friend Foo<T> operator+<> (Foo<T>&, Foo<T>&);  //I am using the template declaration before
};

4. The compiler does not look up dependent base class when looking up non-dependent name (signature not correlate with parametrized type). So the data structure defined in the template base class cannot be referred in the derived class.  You can give a hint with typename like:
typename B::xyz x;
Similarly, if you want to refer a function defined in the template base class, you have to use:
this->f();
as this is always a dependent name, so it will search for the base class.

5. The template keyword is required before dependent names accessing member templates via ., ->, or ::

template <class T> void f(T& x)

{

     int n=x.template convert<3>(pi);  //tell compiler the dependent name is a template, otherwise, it can be treated as "(x.convert <3) > pi".
}

6. Default parameter list as shown in our previous tuple example:
template <class T0=null_type, class T1=null_type, class T2=null_type>  class tuple;

7. Template partial specilization to absorb some parameters
template <int n, T t> struct element; //This is the real template interface I want to use

template <int n, Class TT, class HH> struct element<n, cons<HH, TT>> {

}; //Use it as a different mean.

No comments: