Tuesday, April 7, 2009

Things I Didn't Know about C++: Template Template Parameters

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 Cont::value_type typedef.

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).

6 comments:

Anonymous said...

Joaquim

i have 1 question: do you know build a class pointer('this') template parameter?

Josh Kelley said...

Could you explain a little better what you're wanting to do? I'd be happy to try and help, but you might want to instead try Stack Overflow; a well-written question there can often get a response within minutes.

Anonymous said...

Joaquim

my objective is update my property template class:

template
class property
{
public:

void setContainer(Container* cObject)
{
m_cObject = cObject;
}
............

see the setcontainer() function?
what i need is put it on template prototype.
(these function is what recive the 'this')
how can do a parameter for accept the 'this'?

Josh Kelley said...

I'm sorry, I'm still having trouble understanding you. You mean you want something like this (untested)?

template<typename PropertyType>
class Property
{
public:
template<template <typename> class ContainerType>
void setContainer(ContainerType<PropertyType>* cObject)
{
m_cObject = cObject;
}
};

If you're still having problems, you should probably post on Stack Overflow; it's much better suited for back-and-forth question-and-answer than a blog's comments section is.

Anonymous said...

Joaquim

thanks anyway. i will try get the answer;)
(sorry my english)
but think in these way:
the class have a pointer the 'this'. can i do a parameter for recive it?

Josh Kelley said...

The type of your class is template<typename PropertyType>
class Property, so that's the type of this.