Reputation: 11921
For the sake of clarity, I've removed things like the constructor & destructor etc from the below where they don't add anything to the question. I have a base class that is used to create a common ancestor for a derived template class.
class PeripheralSystemBase {
public:
virtual void someFunctionThatsCommonToAllPeripherals() {}
};
template <class T, uint32_t numPeripherals = 1>
class PeripheralSystem : public PeripheralSystemBase {
public:
PeripheralSystem() : vec(T) {}
std::vector<T> vec; // different types of T is the reason why I need to template this class
};
// A & B declaration & definition are irrelevant here
class A{};
class B{};
// There are multiple different derived variants of PeripheralSystem
// At the moment, each has different template parameters
template <uint32_t customisableParam1>
class DerivedSystem1 : public PeripheralSystem<A, 1> {
public:
DerivedSystem1() : PeripheralSystem<A, 1>() {}
};
template <uint32_t customisableParam1, uint8_t customisableParam2>
class DerivedSystem2 : public PeripheralSystem<B, 1> {
public:
DerivedSystem2() : PeripheralSystem<B, 1>() {/*maybe use customisableParam2 here */}
};
So now I have 2 templates classes, each derived from the same ancestor class, one containing a vector containing type A, the other of type B; each has different template parameters. So far, so good.
Now for the question. I would like to be able to create a container template to contain none, one or more of the derived versions of PeripheralSystem inside it and I think I may be able to use variadic templates to do this, but I've got a bit stuck on the syntax over the past day or so. At compile time, I'd like to be able to create an instance of the container class. Perhaps something like:
template< template<typename ...> class args...>
class ContainerClass {
public:
ContainerClass() : container({args}) {}
std::vector<PeripheralSystem> container;
};
// possible usage
ContainerClass<DerivedSystem1<1>> cc1;
ContainerClass<DerivedSystem2<2, 3>> cc2;
ContainerClass<DerivedSystem1<1>, DerivedSystem2<2, 3>> cc3;
I know the variadic format I'm using isn't right, as I get:
error: expected ',' or '>' in template-parameter-list template< template class args ...> >
What I'm trying to tell the compiler is that I want to supply a variable number of template-type parameters to the template, each of which has a variable number of template parameters. Am I able to do this with variadic templates please? Any suggestions on the correct syntax please?
Upvotes: 2
Views: 1030
Reputation: 157484
You've got your ellipsis in the wrong place. Try:
template<template<typename...> class... Args>
^^^ here
However, you don't actually want template template parameters; since DerivedSystem1<1>
is a type, not a template, you just want ordinary typename parameters:
template<typename... Args>
class ContainerClass {
For the actual container, you can't use vector<PeripheralSystem>
as that is homogeneous and will slice the derived types down to PeripheralSystem
. If you add a virtual destructor to PeripheralSystem
you can use vector<unique_ptr<PeripheralSystem>>
:
template<typename... Args>
class ContainerClass {
public:
ContainerClass() : container{std::make_unique<Args>()...} {}
std::vector<std::unique_ptr<PeripheralSystem>> container;
};
However, tuple
would work just as well and result in fewer allocations:
template<typename... Args>
class ContainerClass {
public:
ContainerClass() : container{Args{}...} {}
std::tuple<Args...> container;
};
Upvotes: 2