具有可变参数模板的模板模板参数

时间:2014-07-17 20:27:03

标签: c++ templates variadic-templates template-templates variadic-functions

为了清楚起见,我删除了构造函数和&amp ;;来自下面的析构函数等,他们不会在问题中添加任何内容。我有一个基类,用于为派生模板类创建一个共同的祖先。

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 */}
};

所以现在我有2个模板类,每个类都派生自相同的祖先类,一个包含一个包含类型A的向量,另一个包含类型B;每个都有不同的模板参数。到目前为止,非常好。

现在提出问题。我希望能够创建一个容器模板来包含其中没有,PeripheralSystem的一个或多个派生版本,我想我可以使用可变参数模板来做到这一点,但我已经有点了在过去一天左右坚持语法。在编译时,我希望能够创建容器类的实例。也许是这样的事情:

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;

我知道我使用的可变格式是不对的,因为我得到了:

  

错误:预期&#39;,&#39;或者&#39;&gt;&#39;在template-parameter-list模板中&lt;   template class args ...&gt; &GT;

我试图告诉编译器的是我想为模板提供可变数量的模板类型参数,每个参数都有可变数量的模板参数。我可以使用可变参数模板吗?有关正确语法的任何建议吗?

1 个答案:

答案 0 :(得分:2)

你的省略号在错误的地方。尝试:

template<template<typename...> class... Args>
                                    ^^^ here

但是,您实际上并不需要模板模板参数;由于DerivedSystem1<1>是一种类型,而不是模板,因此您只需要普通的typename参数:

template<typename... Args>
class ContainerClass {

对于实际容器,您不能使用vector<PeripheralSystem>,因为它是同质的,并且会将派生类型分割为PeripheralSystem。如果您向PeripheralSystem添加虚拟析构函数,则可以使用vector<unique_ptr<PeripheralSystem>>

template<typename... Args>
class ContainerClass {
  public:
    ContainerClass() : container{std::make_unique<Args>()...} {}
    std::vector<std::unique_ptr<PeripheralSystem>> container;
};

但是,tuple同样可以正常运行并减少分配:

template<typename... Args>
class ContainerClass {
  public:
    ContainerClass() : container{Args{}...} {}
    std::tuple<Args...> container;
};