(Knowledge assumptions : templates, std::vector, std::string)
I've recently taken a fancy to Andrei Alexandrescu's Modern C++ design. Its a fabulous book and anyone who is serious about becoming a good C++ programmer ought to read it. However, the book is not for the novice or the faint of heart. Someone on CodeGuru even suggested that the reader wear a helmet while reading this book so that his/her brain would not explode!
Now let me tell my story...
I was writing a string tokenizer in C++. The basic idea was to split a parse string into tokens using another string as the delimiter. The resultant token strings can be returned as a vector of strings.
std::vector<std::string> Tokenize( const std::string& str, const std::string& delimitStr )
{
std::vector<std::string> result;
//////Rest of the code goes here...//////////
return result;
}
Seems pretty sensible, right? Now here's the problem. What if I wanted to give the user the power to specify what kind of STL container he/she wanted to use. Perhaps, a list would be more pertinent, or maybe a deque. In order to do that the Tokenize() function needs to be templated. So here was my first attempt..
template<class Container>
Container Tokenize( const std::string& str, const std::string& tokenStr )
{
Container result;
//////Rest of the code goes here...//////////
return result;
}
Alright, that seems nice enough and the user would have to call this Tokenizer() routine as:
Tokenize<std::list<std::string> >( "breakmeintoathousandpieces", "e" );
Unfortunately, that's redundant because we know that the result is a container of string tokens. Furthermore, the user should not be given the opportunity to misuse the algorithm by specifying something other than std::string for the template argument. It should be fair to simply say:
Tokenize<std::list>( "breakmeintoathousandpieces", "e" );
That won't work however because then the container type would be incomplete. I was wondering how to resolve this problem when it hit me! The use of Template Template Parameters was illustrated for designing Policy classes in Modern C++ Design. It suited my purpose wonderfully!
This is what my revised Tokenizer() function looked like:
template< template<class> class Container >
Container<std::string> Tokenize( const std::string& str, const std::string& tokenStr )
{
Container<std::string> result;
//////Rest of the code goes here...//////////
return result;
}
This example was just to illustrate the use of template template parameters. As Alexandrescu so beautifully put it - "It is as if WidgetManager (the class he templated) were a little code generation engine, and you configure the ways in which it generates code."
If you really have a solid reason to tokenize anything complex, of course, I would recommend using Boost::Tokenizer.