質問

各要素がvectorであるコンテナ(liststd::pairなど)がある場合、各ペアの各要素を反復処理する簡単な方法はありますか?

i.e。

std::vector<std::pair<int,int> > a;
a.push_back(std::pair(1,3));
a.push_back(std::pair(2,3));
a.push_back(std::pair(4,2));
a.push_back(std::pair(5,2));
a.push_back(std::pair(1,5));

その後、値1,3,2,3,4,2,5,2,1,5を反復処理できますか?

同様に、上記のペア要素のフラットなリストを持つコンテナ(同じタイプの)を返すファンクタ/関数のタイプは何ですか?

役に立ちましたか?

解決

ペアのコンテナーを2番目のコンテナーにフラット化するには、独自のインサーターを作成することもできます。

template<class C>
struct Inserter {
    std::back_insert_iterator<C> in;
    Inserter(C& c) : in(c) {}
    void operator()(const std::pair<typename C::value_type, typename C::value_type>& p)
    {
        *in++ = p.first;
    *in++ = p.second;
    }
};

template<class C>
Inserter<C> make_inserter(C& c)
{ 
    return Inserter<C>(c); 
}

// usage example:
std::list<int> l;
std::for_each(a.begin(), a.end(), make_inserter(l));

他のヒント

最初に、独自のイテレータクラスを作成する必要があります。これは、ペア内の位置を示すフラグとcontainer<pair>イテレータをペアにします

2つ目は簡単です。ただし、必要なだけ一般的(同じタイプのコンテナー)にするには、テンプレートtypedef 。ここにベクターのみを示します:

template <class V>
std::vector<V> flatten_pairs(std::vector<std::pair<V,V> > const& a) {
  typedef std::vector<std::pair<V,V> > A;
  std::vector<V> ret;
  for (typename A::const_iterator i=a.begin(),e=a.end();i!=e;++i) {
    ret.push_back(i->first);
    ret.push_back(i->second);
  }
  return ret;
}

テンプレートtypedefを偽造する方法は次のとおりです。

template <class C>
struct same_container;

template <class V>
struct same_container<std::vector<V> > {
  template <class W> struct rebind { typedef std::vector<W> type; };
};

template <class V>
struct same_list<std::list<V> > {
  template <class W> struct rebind { typedef std::list<W> type; };
};

template <class C>
typename same_container<C>::rebind<typename C::value_type::first_type>::type
flatten_pairs(C const& a);

次のコードは、必要に応じてすべての値を出力します:

for ( size_t x = 0; x < a.size(); ++x ) {
    cout << a[x].first << "," << a[x].second << ",";
}

カスタムイテレータを作成するよりも、この簡単な方法の方が好きです。

必要な反復を実行する簡単な方法はありませんが、boost :: iterator_adaptorライブラリを確認するか、独自のイテレータを実装して実行することをお勧めします(複雑すぎてはいけません)。次に、2番目の質問で、std :: copyを新しいイテレーターアダプターで使用できます。

いいえ、本当にstd::pairにはそんなことはありません。代わりにBoost Tupleの使用を検討することをお勧めします。タプルは<=>の拡張バージョンに少し似ており、任意の数の要素(ある程度の制限はありますが、通常は少なくとも10)を許可し、要素へのアクセスもベクトル/配列のようなもの(つまり、名前またはインデックスのいずれかで要素にアクセスできます)。

TR1には、Boostのタプルのサブセットであるstd :: tr1 :: tupleも含まれていますが、メモリが提供される場合、要求している名前/インデックス機能が含まれています。

編集:どちらの場合でも、インデックス表記にはインデックスに compile-time 定数が必要なので、(実行時)ループを記述して要素を反復処理することはできません。タプル-しかし、あなたは少しのメタプログラミングで仕事をすることができます。 Boost Fusionには、必要なものをサポートするためのかなりの部分が含まれています(奇妙な偶然の一致により、タプルはFusionライブラリの一部です)。

ある時点で、独自のイテレータクラスを作成する場合でも、 first および second を使用する必要があります。 (少なくとも、ポータブルな方法で)そこから抜け出す方法はないと思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top