私はSTL文字列で動作する結合関数を持っています。私はこのようなコンテナにそれを適用することができるようにしたい:C++ STL連想コンテナからのキー/値の結合
getFoos(const std::multimap<std::string, std::string>& map) {
return join_values(",", map.equal_range("foo"));
つまり、コレクション内のすべての一致するキーを見つけて、与えられたセパレータを単一の文字列に値を連結します。コンテナの内容全体のためのキーの範囲についてlower_bound()
とupper_bound()
、begin()
/end()
、などと同じこと..
私が得ることができる最も近いは以下の通りです:
template <typename T>
struct join_range_values : public T::const_iterator::value_type::second_type {
typedef typename T::const_iterator::value_type pair_type;
typedef typename pair_type::second_type value_type;
join_range_values(const value_type& sep) : sep(sep) { }
void operator()(const pair_type& p) {
// this function is actually more complex...
*this += sep;
*this += p.second;
}
private:
const value_type sep;
};
template <typename T>
typename T::const_iterator::value_type::second_type join_values(
const typename T::const_iterator::value_type::second_type& sep,
const std::pair<typename T::const_iterator, typename T::const_iterator>& range) {
return std::for_each(range.first, range.second, join_range_values<T>(sep));
}
(私は実感してstd::string
から継承するか、キー/値の型が何であるかは一般的に悪い考えですが、関数のオーバーロードやオーバーライドではないため、仮想デストラクタは必要ありません。暗黙の変換演算子を定義することなく、for_each
の結果を使用してください)。
second_type
とp.second
の代わりにfirst_type
とp.first
を使用して、非常に似た定義があります。join_range_keys
です。私は、同様の定義がstd::set
とstd::multiset
の鍵を結合するために働くと仮定していますが、私はそれを必要としていません。
これらの関数は、さまざまな種類の文字列を持つコンテナに適用できます。キーと値の種類のstring
とwstring
の任意の組み合わせでmap
とmultimap
の任意の組み合わせが動作しているようです:
typedef std::multimap<std::string, std::string> NNMap;
const NNMap col;
const std::string a = join_keys<NNMap>(",", col.equal_range("foo"));
const std::string b = join_values<NNMap>(",", col.equal_range("foo"));
typedef std::multimap<std::string, std::wstring> NWMap;
const NWMap wcol;
const std::string c = join_keys<NWMap>(",", wcol.equal_range("foo"));
const std::wstring d = join_values<NWMap>(L",", wcol.equal_range("foo"));
typedef std::multimap<std::wstring, std::wstring> WWMap;
const WWMap wwcol;
const std::wstring e = join_keys<WWMap>(L",", wwcol.equal_range(L"foo"));
const std::wstring f = join_values<WWMap>(L",", wwcol.equal_range(L"foo"));
これは、いくつかの質問を私に残します:
- 私はにいくつかの簡単な方法をしないのです同じことを達成する?関数シグネチャは特に複雑すぎるようです。
join_values
は、毎回join_values<MapType>
と呼ぶ必要がないようにテンプレートパラメータタイプを自動的に推測させる方法はありますか?join_values
とjoin_keys
の関数と関数をリファクタリングしてコードの大部分を複製しないようにするにはどうすればよいですか?
私はstd::accumulate
に基づいて、わずかに簡単な解決策を見つけたが、範囲内の各要素の文字列全体の2つの完全なコピー操作を必要としているようですので、それは私の知る限り、あまり効率的です。
template <typename T>
struct join_value_range_accum : public T::const_iterator::value_type::second_type
{
typedef typename T::const_iterator::value_type::second_type value_type;
join_value_range_accum(const value_type& sep) : sep(sep) {}
using value_type::operator=;
value_type operator+(const typename T::const_iterator::value_type& p)
{
return *this + sep + p.second;
}
private:
const value_type sep;
};
typedef std::multimap<std::string, std::string> Map;
Map::_Pairii range = map.equal_range("foo");
std::accumulate(range.first, range.second, join_value_range_accum<Map>(","));
オハイオ州の男の子、私はこれを最初に消化する必要があります...ホールド! –