4

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

すなわち

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?

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

4

6 に答える 6

7

最初に、ペア内の位置を示すフラグとイテレータをペアにする独自のイテレータ クラスを作成する必要があり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);
于 2009-11-30T19:33:31.610 に答える
5

The following code will print all values as required:

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

I'd prefer this easy way than creating custom iterator.

于 2009-11-30T19:36:28.080 に答える
3

ペアのコンテナーを 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));
于 2009-11-30T19:55:46.773 に答える
1

There is no simple way of performing the iteration you want, but you may want to take a look at the boost::iterator_adaptor library or implement your own iterator to do it (it should not be too complex). Then, on the second question, you can use std::copy with your new iterator adaptor.

于 2009-11-30T19:35:58.700 に答える
1

No, there really isn't such a thing for std::pair. You might want to consider using a Boost Tuple instead. A tuple is a bit like an expanded version of std::pair that allows an arbitrary number of elements (up to some limit, but normally at least 10), and gives access to the elements something like a vector/array as well (i.e. you can access the elements by either name or index).

TR1 also includes std::tr1::tuple, which is a subset of Boost's tuple, but if memory serves, it still includes the name/index functionality you're asking for.

Edit: note that in both cases, the index notation requires a compile-time constant for the index, so you can't write a (run-time) loop to iterate over the elements in a tuple -- but you can do the job with a bit of metaprogramming. Boost fusion includes quite a bit to support what you'd need (by some strange coincidence, tuple is part of the fusion library).

于 2009-11-30T19:36:27.377 に答える
0

独自の反復子クラスを作成したとしても、ある時点でfirstsecondを使用する必要があります。それを回避する方法はないと思います(少なくとも、移植可能な方法で)。

于 2009-11-30T19:33:15.087 に答える