3

テンプレート引数を typedef で区別するにはどうすればよいですか?

状況: 複数のタイプのリスト (ベクトルとして実装) があります。そして、別の方法で処理したい特別な StringList があります。

typedef std::vector<std::string> StringList;

inline void f(StringList const& list) {
  ...
}

template <typenamte T>
inline void f(std::vector<T> const& list) {
  ...
}

変数が定義されている場合StringListは、最初のバージョンを呼び出したいのですが、変数が定義されている場合std::vector<std::string>は、2 番目のバージョンを呼び出したいと思います。しかし、最初のバージョンStringListstd::vector<std::string>呼び出します。を使用usingすると、同じ動作が得られます。

それが不可能な場合は、合理的な回避策のアイデアがあればよいでしょう。

もちろん、拡張std::vector<std::string>は役に立ちますが、それはまったく良い考えではないため、それらを区別する方法がわかりません。

4

2 に答える 2

4

少なくとも 3 つのオプションがあります。

#include <vector>
#include <string>

// option 1

struct StringList : std::vector<std::string>
{
    // optionally forward the constructors of std::vector that are called
};

// option 2

struct String : std::string
{
    // optionally forward the constructors of std::string that are called
};

typedef std::vector<String> StringList;

// option 3

struct StringTag
{
};

typedef std::allocator<StringTag> StringAllocator;

typedef std::vector<std::string, StringAllocator> StringList;

最初と 2 番目のオプションでは、基本クラスのコンストラクターの一部を転送する必要があります。std::string文字列を文字列リストに追加するときにコピー コンストラクターを転送するだけでよいという前提に基づいて、おそらく 2 番目のオプションの方が適切です。

3 番目のオプションは私のお気に入りです。これは、巧妙なハックであるという理由と、継承や転送を必要としないという理由もあります。コンテナーT内の allocator template-argument の引数が使用されないため、機能します。std

EDIT : C++ 標準は、アロケータがコンテナーのとvalue_type一致する必要があることを意味しvalue_typeます。そのため、標準ライブラリの実装で許可されている場合にのみ、3 番目のオプションを使用できます。そうでない場合は、最初または 2 番目のオプションをお勧めします。

編集 2 : も参照してください:標準のコンテナー要素の型と std::allocator の型が異なる場合、それは間違っていますか?

于 2013-07-30T11:30:54.540 に答える