tags:

views:

2463

answers:

2

I've seen some examples of C++ using template template parameters (that is templates which take templates as parameters) to do policy-based class design. What other uses does this technique have?

+3  A: 

I think you need to use template template syntax to pass a param whose type is a template dependant on another template like this:

template<template<class> class H, class S>
void f(const H<S> &value) {
}

Here, H is a type which is templated, but I wanted this function to deal with all specializations of H.

NOTE: I've been programming c++ for many years and have only needed this once, I find that it is a rarely needed feature (of course handy when you need it!).

EDIT: I've been trying to thing of good examples, and to be honest, most of the time this isn't neccessary, but let's contrive an example. Let's pretend that std::vector doesn't have a typedef value_type. So how would you write a function which can create variables of the right type for the vectors elements? This would have worked.

template<template<class> class V, class T>
void f(const V<T> &v) {
    // this can be V::value_type, but we are pretending we don't have it
    T temp = v.back();
    // do some work on temp
}

This actually doesn't work with std::vector because it has several 2 template params not 1, but if we had a class with the same interface as std::vector but didn't have a value_type, then this would be a way to know the type inside the function.

Finally, here's a version which does work with std::vector:

template<template<class, class> class V, class T>
void f(V<T, std::allocator<T> > &v) {
    // this can be "typename V<T, std::allocator<T> >::value_type", 
    //but we are pretending we don't have it
    T temp = v.back();
    v.pop_back();
    // do some work on temp
    std::cout << temp << std::endl;
}

which you can use like this:

f<std::vector, int>(v); // v is of type std::vector<int> using the standard allocator
Evan Teran
+4  A: 

Here is a simple example taken from 'Modern C++ Design - Generic Programming and Design Patterns Applied' by Andrei Alexandrescu:

He uses a classes with template template parameters in order to implement the policy pattern:

// Library code
template <template <class> class CreationPolicy>
class WidgetManager : public CreationPolicy<Widget>
{
   ...
};

He explains: Typically, the host class already knows, or can easily deduce, the template argument of the policy class. In the example above, WidgetManager always manages objects of type Widget, so requiring the user to specify Widget again in the instantiation of CreationPolicy is redundant and potentially dangerous.In this case, library code can use template template parameters for specifying policies.

The effect is that the client code can use 'WidgetManager' in a more elegant way:

typedef WidgetManager<MyCreationPolicy> MyWidgetMgr;

Instead of the more cumbersome, and error prone way that a definition lacking template template arguments would have required:

typedef WidgetManager< MyCreationPolicy<Widget> > MyWidgetMgr;
yoav.aviram