Continuing my series on things I didn't know about C++...
I knew about templates, and I knew about parameters to templates, but I did not know about template template parameters, which are useful when dealing with containers and policies and, if nothing else, are worth learning about for having such a "pleasingly repetitious name" (in C++ author Stephen Dewhurst's words).
A template template parameter is simply a template parameter that is itself a template. Dewhurst gives the example of a
Stack template that can be customized to use a particular underlying storage container:
template <typename T, template <typename> class Cont> class Stack; Stack<int, List> stack_of_ints;
Without template template parameters, the base type (
int in this case), which hampers readability at best and could be a source of errors at worst:
template <typename T, typename Cont> class Stack; Stack<int, List<int> > stack_of_ints; Stack<double, List<int> > stack_of_doubles_badly_truncated_to_ints;
Template template parameters can be used anywhere you need to let the caller customize an algorithm or class for a particular container, policy, or similar:
- A stack or other higher-level container can be instantiated using any lower-level container, as in Dewhurst's example.
- A class or function can be customized with a policy template. Andrei Alexandrescu gives an example of this in section 1.5 of Modern C++ Design. (His example is also summarized in this Stack Overflow post.)
- Template template parameters can be used when you need to know both the type of a template and how that template was instantiated, although this comes up less often than you might initially think, because there are often better ways to find the types involved. For example, there's no need to declare
template <typename T, template <typename> class Cont> void ProcessContainedObjects(Cont<T>& cont)to let ProcessContainedObjects know what T is when any well-written container will define the
Template template parameters are a useful addition to the C++ template programming toolbox, alongside techniques such as partial template specialization, type traits, concepts (also in C++0x), and C++0x's variadic templates (which can be simulated in C++03 to some extent by using default template arguments or by using Boost Preprocessor to create overloads of every arity from 1 through a #define'd limit).