web-dev-qa-db-ja.com

テンプレートコンテナを持つテンプレートクラス

テンプレート引数として異なるコンテナを使用してテンプレートクラス(アダプタ)を宣言するにはどうすればよいですか?たとえば、クラスを宣言する必要があります。

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

そして、私はベクトルに基づいてそれが欲しいです。それをハード定義する方法は? (誰かがそのような宣言を書かないようにするMyMultibyteString<int, vector<char>>)。

さらに、そのような構築を実装する方法:

MyMultibyteString<int, std::vector> mbs;

テンプレート引数をコンテナに渡さずに。

35
DuXeN0N

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

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

これにより、次のように記述できます。

MyMultibyteString<int, std::vector> mbs;

コンパイル 実例 です。上記を記述する別の方法は次のとおりです。

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

そして、対応する 実例 です。

注意しなければならない唯一のことは、テンプレートテンプレートパラメータ宣言の引数の数とタイプが、テンプレート引数として渡したい対応するクラステンプレートの定義の引数の数とタイプと正確に一致する必要があることです。これらのパラメータの一部がデフォルト値を持っている可能性があるという事実。

たとえば、 クラステンプレートstd::vectorは、2つのテンプレートパラメーター (要素タイプとアロケータータイプ)を受け入れますが、2番目のパラメーターにはデフォルト値std::allocator<T>があります。このため、notと書くことができます:

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::setとは異なり ため、テンプレートテンプレートパラメータとしてstd::vectorstd::vectorの両方を受け入れることができる1つのクラステンプレートを作成することはできません。 std::setクラステンプレートはthree template parameters を受け入れます。

72
Andy Prowl

これを解決する別のアプローチは、可変長テンプレートを使用することです。これにより、上記のコメントで提案されているように任意のコンテナを使用できます。実装は次のとおりです。

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