I'm trying to understand C++ template templates by implementing a generic container class. Here is the code:
using namespace std;
template <typename T, template <typename STORETYPE> class Container>
class Store {
public:
~Store() {};
Store() {};
void someFunc( const T & ) {};
//...
private:
Container<T> storage;
};
int main(int argc, char *argv[])
{
Store<int,deque> myStore; // error here, won't compile!
}
The code above generates a compiler error message. The error message is:
"template template argument has different template parameters than its corresponding template template parameter Store aStack1;
I don't know why. What's wrong?
Your issue is that std::deque
(and other standard containers) doesn't just take a single template argument. As well as the stored type, you can specify an allocator functor type to use.
If you don't care about these additional arguments, you can just take a variadic template template and be on your way:
template <typename T, template <typename...> class Container>
// variadic ^^^
class Store {
If you also want to support passing of optional arguments to your container type, you can forward them on like this:
template <template <typename ...> class Container, typename T, typename... ContainerArgs>
class Store {
//...
Container<T,ContainerArgs...> storage;
};
Then instantiate like so:
Store<deque,int> myStore;
Store<deque,int,MyIntAllocator> mySpecialStore;
However, you might just want to extract the template arguments using specialization:
template <typename Container>
class Store;
template <template <typename...> class ContainerType, typename T, typename... OtherArgs>
class Store<ContainerType<T,OtherArgs...>>
{
//...
};
This will let client code instantiate like this:
Store<deque<int>> myStore;
Store<deque<int,MyIntAllocator>> mySpecialStore;
Store<T> myOtherStore; //where T is some specialized container type
std::deque
is defined as
template <class T, class Allocator = allocator<T> > class deque;
So you should change the definition of Store
to match:
template <typename T, template <typename...> class Container>
class Store {
But actually you don't even need template template parameters for this. You can achieve even more generality just passing a container type as parameter, so for example Storage
would support even std::map
:
template <typename Container>
class Store {
public:
using value_type = typename Container::value_type;
~Store() {};
Store() {};
void someFunc( const value_type& ) {};
//...
private:
Container storage;
};
Store<std::map<int, float>> myStore;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With