Multiple Variadic Parameter Pack for Template Class

前端 未结 3 1326
予麋鹿
予麋鹿 2021-02-04 12:44

I am using variadic parameter packs for policy based class design.

template 
class IShader : public Policies... {

};
         


        
相关标签:
3条回答
  • 2021-02-04 13:28

    Make a nested class, with each layer having one variadic pack. In essence:

    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;
    //...
    

    Define any function of Type outside both classes, but inside the header, or gcc will get confused.

    For a more complete use case, see my answer here

    0 讨论(0)
  • 2021-02-04 13:45

    I think the simplest answer is to create template type wrappers for your parameter packs. For example:

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

    Then you can declare your IShader type:

    template <typename... T>
    class IShader;
    

    Create your implementation as a specialization. Note that in a specialization, you can have multiple parameter pack arguments.

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

    Then you can even allow the user to specify the arguments in different orders (make sure you forward the constructors if doing it this way via inheritance):

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

    If you're being really fancy, you can even use metaprogramming tricks to allow the arguments in any order without enumerating all orders. This is left as an exercise to the reader. :)

    0 讨论(0)
  • 2021-02-04 13:47

    In the discussion comments you expressed a willingness to consider some kind of indirection, or "a wrapper of some kind for the attribute list".

    A lightweight std::tuple-based wrapper, together with specialization, might work here:

    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... {
    
    // ...
    
    };
    

    The goal here is to use a template instance along the lines of:

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

    And cross your fingers that this is going to match the specialized template declaration, at which point both parameter packs are available for the template specialization to use, individually.

    0 讨论(0)
提交回复
热议问题