可変個引数テンプレートの世界への旅を続けると、別の問題に遭遇しました。
次のテンプレート クラスを想定します。
template < typename T >
struct foo
{
//default implementation
};
次のように、可変個引数テンプレートのインスタンス化に部分的に特化することができます。
template < template < typename ... > class T, typename ...Args >
struct foo< T< Args... > >
{
//specialized implementation
};
これによりfoo< int >
、デフォルトの実装とfoo< std::tuple< int, char > >
特殊な実装に対応します。
ただし、複数のテンプレート パラメーターを使用すると、事態はさらに複雑になります。たとえば、次のテンプレート クラスがあるとします。
template < typename T, typename U >
struct bar {};
で行ったように、それを部分的に特化したいのですがfoo
、それはできません。
template < template < typename ... > class T, typename ...TArgs,
template < typename ... > class U, typename ...UArgs >
struct bar< T< TArgs... >, U< UArgs... > > {};
//This would correspond to the specialized version with
//T=std::tuple,
//TArgs=int,char
//U=std::tuple,
//UArgs=float
bar< std::tuple< int, char >, std::tuple< float > > b;
確かに、私が正しければ、テンプレート パラメーター パックは 1 つしか持てず、パラメーター リストの最後に配置する必要があります。テンプレート宣言でこれが必須である理由は理解していますが、特定の部分的なテンプレートの特殊化 (上記の例など) では、これは問題になりません。
複数のテンプレート パラメーター パックを使用して部分的なテンプレートの特殊化を実現することは可能ですか?
編集:今、私はばかげていると感じています...上記のコードは完全にコンパイルされます(少なくともgcc 4.5では)。コンパイル エラーは、複数のパラメーター パックが原因ではなく、メンバー関数のパラメーターとして使用されたことが原因でした。の部分的な特殊化で、とパラメータbar
の両方を受け取るメンバー関数を定義しようとしました。TArgs
UArgs
template < template < typename ... > class T, typename ...TArgs,
template < typename ... > class U, typename ...UArgs >
struct bar< T< TArgs... >, U< UArgs... > >
{
void method( TArgs... targs, UArgs... uargs ) //compile error here
{
}
};
メンバー関数の宣言で、gcc がエラーを表示します
パラメータ パックは、パラメータ リストの最後にある必要があります。
私が知る限り、コンパイラは、特定のテンプレートのインスタンス化に対して正しいメンバー関数を定義できるはずです。たとえばbar< std::tuple< int, char >, std::tuple< float > >
、メンバー関数を含める必要がありますvoid method( int, char, float )
。私は何か間違ったことをしていますか?それとも、不可能なことをしようとしていますか? もしそうなら、これが不可能な正当な理由はありますか?