Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template definition with template template parameter for class that can specialize, for instance, to std::vector<std::string> or std::map<std::tree>

I want to create a template class that can hold any combination of container and containee. For example, a std::vector<std::string> or std::map<std::tree>, for instance.

I have tried a lot of combinations, but I must admit that the complexity of templates overwhelms me. The closes I have made compile is something like this:

template <class Vector, template <typename, class Containee = std::string> class Container>
class GenericContainer
{
    Container<Containee> mLemario;
};

Although it compiles so far, then, when I want to instantiate it I rreceive lots of errors.

MyContainer<std::vector, std::string> myContainer;

Am I using the correct approach to create that kind of class?

like image 568
Hola Mundo Avatar asked Aug 22 '17 07:08

Hola Mundo


2 Answers

For std::vector (and the like) @songyuanyao provided an excellent answer. But since you also mentioned std::map, I'll add a simple extension of @songyuanyao's answer, online.

#include <iostream>
#include <vector>
#include <string>
#include <map>

template <template <typename...> class Container, typename Containee = std::string, typename... extras>
class GenericContainer
{
    Container<Containee, extras ...> mLemario;
    // Use 'Containee' here (if needed) like sizeof(Containee) 
    // or have another member variable like: Containee& my_ref.
};

int main()
{
    GenericContainer<std::vector, std::string> myContainer1;
    GenericContainer<std::vector, std::string, std::allocator<std::string>> myContainer2; // Explicitly using std::allocator<std::string>
    GenericContainer<std::map, std::string, int> myContainer3; // Map: Key = std::string, Value = int
}
like image 108
Jonas Avatar answered Oct 01 '22 22:10

Jonas


I want to create a template class that can hold any combination of container and containee

You should use parameter pack for template template parameter Container, and Containee, then they could be used with arbitrary number/type of template parameters. e.g.

template <template <typename...> class Container, typename... Containee>
class GenericContainer
{
    Container<Containee...> mLemario;
};

then

GenericContainer<std::vector, std::string> myContainer1;
GenericContainer<std::map, std::string, int> myContainer2;
like image 22
songyuanyao Avatar answered Oct 02 '22 00:10

songyuanyao