I want to build a Stack class so the user will be able to choose which container he wants to use for the implementation of the Stack. For example, List/Vector.
Partial code:
stack.h
#ifndef STACK_H_
#define STACK_H_
template <typename T, template<typename T> class ContainerType>
class Stack{
ContainerType<T> container;
public:
Stack() : container(ContainerType<T>()){}
};
#endif /* STACK_H_ */
test.cpp
#include "stack.h"
#include <vector>
int main(){
Stack<int, std::vector<int> > stack;
return 0;
}
Well, it doesn’t compile. I get the next errors on line:
Stack<int, std::vector<int> > stack;
Errors:
expected a class template, got `std::vector<int, std::allocator<int> >' test.cpp
invalid type in declaration before ';' token test.cpp
type/value mismatch at argument 2 in template parameter
list for `template<class T, template<class T> class ContainerType>
class Stack' test.cpp
First, it would be
std::vector, and nothing else, becausevectorresides in thestdnamespace and you are asking for a template template parameter, whilestd::vector<int>is not a template anymore. Next, astd::vectoractually takes two template parameters, one for the type and the other for the allocator:Now, this only enables containers with two template parameters as the underlying type, so you’re better off with what the standard does: take it as a normal type:
To ensure that the underlying type has the same
T, you can do a fake “static assert”, or if you have a C++0x enabled compiler, you can do an actual static assert:This works because if
Tis different from the used container’sT, it will be atypedef char ERROR_different_vale_type[-1], and an array of negative size can’t possibly exist, which causes a compiler error. 🙂 Now, with C++0x you can juststatic_assertthat:For convenience, you can now specify a default template argument for the common case:
And at this point you can just use
std::stackwhich does exactly this (though it usesstd::dequeas the underlying type). 🙂