2013-05-16 10 views
30

テンプレート引数として異なるコンテナを持つテンプレートクラス(アダプタ)を宣言するにはどうすればよいですか? テンプレートコンテナを持つテンプレートクラス

template<typename T, typename Container> 
class MyMultibyteString 
{ 
    Container buffer; 
    ... 
}; 

そして、私は私のベクトルに基づいて、それをしたい: は例えば、私はクラスを宣言する必要があります。どのようにそれをハード定義するには? (誰かがそのような宣言を書くのを防ぐために MyMultibyteString<int, vector<char>>)。

また、このような構成の実装方法:容器にテンプレート引数を渡すことなく

MyMultibyteString<int, std::vector> mbs; 

を。これは、あなたが書くことができるようになる

template<typename T, template <typename, typename> class Container> 
//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
class MyMultibyteString 
{ 
    Container<T, std::allocator<T>> buffer; 
    // ... 
}; 

答えて

59

あなたはテンプレートテンプレートパラメータを使用する必要があります

ここ
MyMultibyteString<int, std::vector> mbs; 

はコンパイルlive exampleです。上記の書き込みの別の方法は次のようになります。

template<typename T, 
    template <typename, typename = std::allocator<T>> class Container> 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
class MyMultibyteString 
{ 
    Container<T> buffer; // <== No more need to specify the second argument here 
    // ... 
}; 

そしてここでは、対応するlive exampleです。

注意する必要があるのは、テンプレートテンプレートパラメータ宣言の引数の数とタイプが、対応するクラステンプレートの定義の引数の数と型と正確に一致する必要がありますそれらのパラメータのいくつかにデフォルト値があるかもしれないという事実にかかわらず。

たとえば、the class template std::vector accepts two template parameters(要素タイプとアロケータタイプ)ですが、2番目の値はデフォルト値std::allocator<T>です。このため、あなたは可能性がありない書き込み:

template<typename T, template <typename> class Container> 
//        ^^^^^^^^ 
//        Notice: just one template parameter declared! 
class MyMultibyteString 
{ 
    Container<T> buffer; 
    // ... 
}; 

// ... 

MyMultibyteString<int, std::vector> mbs; // ERROR! 
//      ^^^^^^^^^^^ 
//      The std::vector class template accepts *two* 
//      template parameters (even though the second 
//      one has a default argument) 

これはあなたが原因std::vectorとは異なり、テンプレートテンプレートパラメータとしてstd::setstd::vectorの両方を受け入れることができます1つのクラステンプレートを記述することはできないことを意味し、 the std::set class template accepts three template parameters。これを解決する

+0

どのような素晴らしい、徹底的な答え。 –

+0

@ScottJones:便利だとうれしいです:) –

+3

@ScottJonesステートメントに関して: 'これは、std :: setとstd :: vector'の両方を受け入れることができる1つのクラステンプレートを書くことができないことを意味します: variadicテンプレートは問題を解決しますか? http://stackoverflow.com/a/20499809/2436175 – Antonio

2

別のアプローチは、可変長引数テンプレートを使用していると、上記のコメントで示唆したように、そのであなたは、任意のコンテナを使用することができ、ここでimplemenationです:

template<template <typename... Args> class Container,typename... Types> 
class Test 
{ 
    public: 
    Container<Types...> test; 

}; 
int main() 
{ 
    Test<std::vector,int> t; 
    Test<std::set,std::string> p; 
    return 0; 
} 
関連する問題