0
#include <iostream>

template <typename T>
class Container1
{
    // some implementation.
};

template <typename T>
class Container2
{
    // some implementation.
};

template <typename type, typename container>
class CreateContainer
{
    container<type> createContainer()
    {
        return container<type>();
    }

    container<const type> createConstContainer()
    {
        return container<const type>();
    }
};

int main()
{
    // doesn't compile.
    CreateContainer<int, Container1> createContainer1;
    CreateContainer<int, Container2> createContainer1;

    // don't wanna do that:
    // CreateContainer<Container2<int>, Container2<const int>, int> createContainer1;
    // I might need to know the type inside the container (the int) so it's passed as well.
}

Consider this code, I'm creating a factory class that creates a normal containers as long as containers with const elements. Thats just an example. What I'm actually doing is that I want to return an iterator to some container and a const iterator to the same container. But the most of the code is not relevant to the problem so I made up an example. I wanna pass the containers as a template argument and then specify inside the factory class what arguments to pass to the container. If I don't pass the containers without their argument list, I'll have to pass the type inside the container, the normal container type and the const container type in the argument list of the factory class which is redundant.

StackExchange123
  • 1,871
  • 9
  • 24

1 Answers1

2

You can make container a template template parameter, and you declare createContainer1 twice in main. This compiles:

#include <iostream>

template <typename T>
class Container1 {};

template <typename T>
class Container2 {};

template <typename type, template<class> class container>
class CreateContainer
{
    container<type> createContainer()
    {
        return container<type>();
    }

    container<const type> createConstContainer()
    {
        return container<const type>();
    }
};

int main()
{
    CreateContainer<int,Container1> createContainer1;
    CreateContainer<int,Container2> createContainer2;
}

Note that this assumes that the container template parameter has a single type parameter. It wont work for eg for a template <typename T,size_t foo> struct container3 {};, but it could be made to work, if you need that.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • a tiny disclaimer: I am not familiar with >C++11 template stuff and Jespers comment makes me suspect that I am missing something, will try to read up on it. In any case the above should work as expected – 463035818_is_not_an_ai Apr 17 '20 at 16:48
  • Thank you! Thats exactly what I was looking for. I don't understand what it won't work for tho. https://ideone.com/TPC93X the code here is working fine and it takes couple of template arguments. – StackExchange123 Apr 17 '20 at 17:32
  • @StackExchange123 because in that example `container` is a template that takes a type parameter and a size_t parameter, in that case you cannot use it with a `template struct container42 {};`. For a fixed number of template parameters it works , but you cannot pass a template with a different number of parameters (at least not without a bit of helper code) – 463035818_is_not_an_ai Apr 17 '20 at 17:34
  • Can you write an example that won't work? Thanks in advance. – StackExchange123 Apr 17 '20 at 17:39
  • 1
    @StackExchange123 already did that ;) you have to uncomment one line to break it, because I already included the fix https://ideone.com/e.js/CLKWCI – 463035818_is_not_an_ai Apr 17 '20 at 17:42