FAQ Articles Links Personal

Template Power

Scope

Most C++ programmers use templates as the compile-time polymorphic mechanism for writing generic algorithms and classes. Many of them use template template types in order to be more explicit about what kind of types they're expecting. What about template template template types ? Or even template template template template types ? Not sure what I mean ? Continue reading.

Introduction

Consider a template class that takes a single template type:

template< typename T >

struct First {

T first_;

};

Now, consider another template class that takes our first class as a template type:

template< typename T, template <class> class F >

struct Second {

F<T> second_;

};

The "F" template type is known as a template template type. Now, what happens if we want another class template that takes our second class as a template type ?

Template template template types

Writing such a template only requires just a bit of care in writing it right:

template

<

typename T,

template <class> class F,

template < class, template <class> class > class S

>

struct Third {

S<T,F> third;

};

That wasn't too hard. The first template type is T, which is needed to instantiate First. The second is the actual First type, needed to instantiate the second, and is a template template type. The third however is the actual Second type and is a template template template type. This third template type is read as "any type who's template arguments are a non-template type and a template type that takes a template type of its own, namely S< NonTemplateType, TemplateType<SomeType > >.

You can declare an object of class Third which, for instance, holds an int, like this:

Third< int, First, Second > object; object.third_.second_.first_ = 1;

Somewhat easier than without using template template types, or template template template types:

Third< Second< First< int > > > object; // alternative 1

Or, even worse:

Third< int, First< int >, Second< First< int > > > object; // alternative 2

However, these approaches aren't always interchangeable. For instance, if you wanted to inherit from both First and Second, you wouldn't be able to use alternative 1. Alternative 2 is too messy and should never be an option.

Even if using template ... template types increases the coupling between classes - they need to know more about each other, specifically what template types they have - this could sometimes avoid some errors, and definitely allows some interesting possibilities. For instance, class Third could have an extra template argument and hold two instances of class Second, each with a different type. Class Third could inherit from two different Second types.

Template template template template types ?

With template... template types, sky's the limit (or your compiler's limitations). Here's how a template template template template class Fourth would look like:

template

<

typename T,

template < class > class F,

template < class, template <class> class > class S,

template

<

class,

template< class > class,

template< class, template<class> class > class

> class H

>

struct Fourth {

H< T, F, S > fourth_;

};

Phew, that's a lot of class ! It's not pretty code, but you can declare a object of type Fourth easily:

Fourth< int, First, Second, Third > object; object.fourth_.third_.second_.first_ = 1;

An actual use of template... template types

template< typename Return, typename ArgumentTuple >

struct ErrorPolicy { /*...*/ };

 

template <

typename Return, typename ArgumentTuple, typename Map,

template <class,class> class ErrPolicy >

struct ProcessPolicy : public ErrPolicy< Return, ArgumentTuple > { /* ... */ };

 

template <

typename Return, typename ArgumentTuple, typename Key,

template <class,class> class ErrPolicy,

template <class, class, class, template <class,class> class > class ProcPolicy >

struct ChainOfResponsability : public ProcPolicy<

Return, ArgumentTuple, std::map< Key, ArgumentTuple >, ErrPolicy > {

/*...*/

};

As a side note, std::map's second template type is not really ArgumentTuple in my Chain of Responsibility article, but it's not important for this article. I preferred not using template template template types in my previous article to avoid confusing anyone with it.

 

References

 


© Ciobanu Vladimir, 2004