Multiple Variadic Parameter Pack for Template Class
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.
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. :)