繁体   English   中英

模板类的多变量参数包

[英]Multiple Variadic Parameter Pack for Template Class

我正在使用可变参数包进行基于策略的类设计。

template <APITypes APIType, class... Policies>
class IShader : public Policies... {

};

策略是在调用时定义的,或者如果没有指定则使用默认值。 当我需要添加另一个可变参数包时出现问题:

template <AttributeType... Attributes, APITypes APIType, class... Policies>
class IShader : public Policies... {

};

这会导致错误“模板参数包必须是最后一个模板参数”。 我计划使用属性包来更改至少一项策略的行为。 但是我不知道如何在一个模板类中获得两个可变参数包。

我认为最简单的答案是为参数包创建模板类型包装器。 例如:

template <AttributeType... T>
struct Attributes {};

template <typename... T>
struct Policies {};

然后你可以声明你的IShader类型:

template <typename... T>
class IShader;

将您的实现创建为专业化。 请注意,在专门化中,您可以拥有多个参数包参数。

template <AttributeType... AttributeList, ApiTypes APIType, typename... PolicyList>
class IShader<Attributes<AttributeList...>, ApiType, Policies<PolicyList...>> 
    : public PolicyList...
{
    ...
};

然后,您甚至可以允许用户以不同的顺序指定参数(如果通过继承以这种方式执行,请确保转发构造函数):

template <AttributeType... AttributeList, ApiTypes APIType, typename... PolicyList>
struct IShader<ApiType, Policies<PolicyList...>, Attributes<AttributeList...>
    : public IShader<Attributes<AttributeList...>, ApiType, Policies<PolicyList...>>
{
    using IShader<Attributes<AttributeList...>, ApiType, Policies<PolicyList...>>::IShader;
};

如果你真的很喜欢,你甚至可以使用元编程技巧来允许任何顺序的参数而不枚举所有的命令。 这留给读者练习。 :)

在讨论评论中,您表示愿意考虑某种间接,或“属性列表的某种包装”。

一个轻量级的基于std::tuple的包装器,以及特化,可能在这里工作:

template <typename attribute_tuple, APITypes APIType,
          typename policy_tuple> class IShader;

template <AttributeType... Attributes, APITypes APIType,
          class... Policies>
class IShader<std::tuple<Attributes...>, APIType,
              std::tuple<Policies...>> : public Policies... {

// ...

};

这里的目标是使用以下行的模板实例:

IShared<std::tuple<Attribute1, Attribute2>, APITypeFoo,
        std::tuple<Policy1, Policy2>> ishared_instance;

并指出这将与专门的模板声明相匹配,此时两个参数包都可供单独使用的模板专业化。

制作一个嵌套类,每一层都有一个可变参数包。 在本质上:

template<class... ArgsA> class Wrapper {
public:
    template<class... ArgsB> class Type {
        //Here you have access to both template packs
        //...
    }
}
//Use like this:
Wrapper<int, char, long unsigned int>::Type<float, double> a;
//...

在两个类之外定义任何Type函数,但在头文件中,否则 gcc 会混淆。

有关更完整的用例,请在此处查看我的答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM