How to instantiate with other than defaulted parameters in a template template parameter
I'm trying to cement my understanding of template template parameters. In C++ Templates the Complete Guide (Vandervoorde, Josuttis), they have an example on page 52 that I want to use as indicated in this image:
(I'm also trying to learn how to use images from Picasa on stackoverflow so if the above doesn't work, here's a slightly more verbose version)
Original Code from Book
template <typename T,
template <typename ELEM, typename ALLOC=std::allocator<ELEM> > class CONT=std::vector>
class Stack
{
private:
CONT<T > elems; //Why doesn't CONT<T, ALLOC> elems; compile?
};
The don't show you how to use this for a different allocator. They do show a different conta开发者_开发技巧iner as:
Stack<int, std::deque> my_deque_stack;
and in my naivete I tried:
Stack<int, std::deque<int, std::allocator<int> > > my_deque_int_stack;
I also tried in the private section defining CONT as
CONT<T, ALLOC>
but that too generates a compiler error. I'm wondering what the correct syntax is for using the Stack template where I want to use a deque but want to specify a different allocator. I read some similar posts here that indicate sprinkling typename or template qualifiers around and I tried a couple but couldn't seem to find the magic formula.
The parameter definitions inside CONT are actually not used by the compiler. The template-template parameter CONT is actually similar to a function, which takes 2 types input and return a new type:
// pseudo code
type Stack(type T, type(*CONT)(type ELEM, type ALLOC = etc)) {
return CONT(T);
}
and like the normal function pointer declarations, the names ELEM, ALLOC are actually ignored by the compiler.
What the compiler sees would be just
template <typename T,
template <typename E, typename = std::allocator<E> > class CONT = std::vector>
struct Stack { ... };
Therefore, you cannot use ALLOC at all.
So to solve it? Well, you pass an extra parameter! Just like the case in a normal C++ function:
// pseudo code
type Stack(type T, type(*CONT)(type, type), type ALLOCATOR = etc) {
// ^^^^^^^^^^^^^^^^^^^^
return CONT(T, ALLOCATOR);
}
The corresponding actual template declaration would be
template <typename T,
template <typename, typename> class CONT = std::vector,
typename ALLOCATOR = std::allocator<T> >
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
struct Stack {
...
CONT<T, ALLOCATOR> elems;
};
//...
Stack<int, std::vector, std::allocator<int> > s;
精彩评论