模板类的多变量参数包

Jam*_*mes 8 c++ variadic-templates c++14

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

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

};
Run Code Online (Sandbox Code Playgroud)

调用时会定义策略,如果未指定,则使用默认值定义策略.当我需要添加另一个可变参数包时,问题出现了:

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

};
Run Code Online (Sandbox Code Playgroud)

这会导致错误"模板参数包必须是最后一个模板参数".我打算使用属性包来更改至少一个策略的行为.但我无法弄清楚如何在一个模板类中获得两个可变参数包.

md5*_*d5i 9

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

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

template <typename... T>
struct Policies {};
Run Code Online (Sandbox Code Playgroud)

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

template <typename... T>
class IShader;
Run Code Online (Sandbox Code Playgroud)

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

template <AttributeType... AttributeList, ApiTypes APIType, typename... PolicyList>
class IShader<Attributes<AttributeList...>, ApiType, Policies<PolicyList...>> 
    : public PolicyList...
{
    ...
};
Run Code Online (Sandbox Code Playgroud)

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

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;
};
Run Code Online (Sandbox Code Playgroud)

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


Sam*_*hik 6

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

一个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... {

// ...

};
Run Code Online (Sandbox Code Playgroud)

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

IShared<std::tuple<Attribute1, Attribute2>, APITypeFoo,
        std::tuple<Policy1, Policy2>> ishared_instance;
Run Code Online (Sandbox Code Playgroud)

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