2016-05-13 11 views
7

私は、ポリシーベースのクラス設計のためにバリディックなパラメータパックを使用しています。テンプレートクラス用の複数のVariadic Parameter Pack

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

}; 

ポリシーは、呼び出されたときに定義されます。指定されていない場合は、デフォルトでポリシーが定義されます。私は別の可変引数パラメータパックを追加する必要があるときに問題が来る:

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

}; 

これはエラーになり、「テンプレートパラメータパック最後のテンプレートパラメータでなければなりません」。私は、属性パックを使用して少なくとも1つのポリシーの動作を変更する予定です。しかし、私は1つのテンプレートクラスに2つのvariadicパラメータパックを取得する方法を考えることができません。

+1

できません。あなたはテンプレート/クラスデザインを再考する必要があります。 –

+1

何らかの間接指定さえありませんか?属性リストのための何らかの種類のラッパーを言う。またはテンプレートのテンプレート? – James

+6

あなたはいつも 'IShader 、APIType、Policies >' – chris

答えて

5

議論のコメントでは、ある種の間接参照や「属性リストのための何らかの種類のラッパー」を検討する意思を表明しました。

軽量std::tupleベースのラッパー、一緒専門で、ここで働いかもしれませんが:

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

そして、あなたを渡る:

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

// ... 

}; 

ここでの目標は、の線に沿ってテンプレートのインスタンスを使用することですこれが特殊なテンプレート宣言と一致することを指しています。この時点で、両方のパラメータパックをテンプレート特殊化で個別に使用できます。

+0

IShaderクラスのオブジェクトを宣言するときにタプルが必要ですか? – James

+0

@Jamesタプルは必要ですが、型としてのみ必要です。実際にインスタンス化されるタプルはありません。 – md5i

+0

ここでも 'IShared 、APITypeFoo、 std :: tuple > ishared_instance;'?実装を提供する特殊化を使用せず、デフォルトを使用します。このようなクラスを使用することはできません 'IShared ishared_instance;'? – James

6

最も簡単な答えは、パラメータパックのテンプレートタイプラッパーを作成することだと思います。たとえば:

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

あなたが本当にされている場合あなたはすべての注文を列挙することなく、任意の順序で引数を許可するためにメタプログラミングトリックを使用することもできます。これは読者の練習として残されています。 :)

関連する問題