1

Given the following code here in IDEOne:

#include <iostream>
#include <vector>
#include <list>

template<typename T>
class MyVectorCollection
{
    using collection = std::vector<T>;
};

template<typename C, typename T>
class MyGenericCollection
{
    using collection = C;
};

template<typename C, typename T>
class MyMoreGenericCollection
{
    using collection = C<T>;
};

int main() {
    // your code goes here
    MyVectorCollection<int> a;
    MyGenericCollection<std::list<int>, int> b;
    MyMoreGenericCollection<std::list, int> c; // How to do this?
    return 0;
}

I get the error:

prog.cpp:20:24: error: ‘C’ is not a template
     using collection = C<T>;
                        ^
prog.cpp: In function ‘int main()’:
prog.cpp:27:43: error: type/value mismatch at argument 1 in template parameter list for ‘template<class C, class T> class MyMoreGenericCollection’
     MyMoreGenericCollection<std::list, int> c;
                                           ^
prog.cpp:27:43: note:   expected a type, got ‘list’

How can I write my code such that I can use a C<T> at compile time without having an explicit list of potential specialisations, and avoiding macros, if possible? I realise std::list isn't a typename, but I don't know how to progress, and I have been unable to find a similar question here.

(Note that this is just an MCVE, my actual usage is much more involved.)

Ken Y-N
  • 14,644
  • 21
  • 71
  • 114

1 Answers1

1

Just to tidy up, here is the solution. The search term I was looking for is template template, and whilst I did find a possible duplicate, I think this question and answer is much simpler to follow.

So, thanks to the hint from @Some programmer dude, I looked up template template and updated the code to this, which does compile:

template<template<typename, typename> class C, typename T>
class MyMoreGenericCollection
{
    using collection = C<T, std::allocator<T>>;
};

We declare the first template parameter as a template itself, and remembering that the standard library constructors take two parameters, we need to make the inner template take two parameters. There is (as far as I am aware) no way to automatically use the default second parameter, so for the sake of this example I explicitly state the default.

I could of course add a third parameter to the master template that could be used to specify the allocator, which itself would also be a template, but I leave that as an exercise for th reader.

Ken Y-N
  • 14,644
  • 21
  • 71
  • 114