Frage

Wenn ich einen Behälter zur Verfügung haben (vector, list, usw.), wobei jedes Element ein std::pair ist, gibt es eine einfache Möglichkeit, jedes Element eines jeden Paares iterieren?

d.

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));

und dann über den Wert iterieren zu können: 1,3,2,3,4,2,5,2,1,5

Und welche Art von Funktors / Funktion mir einen Behälter (des gleichen Typs) mit einer flachen Liste der Paare Elemente wie oben zurückkehren würde?

War es hilfreich?

Lösung

Um die Behälter von Paaren in einem zweiten Behälter abflachen könnten Sie auch einfach Ihre eigenen Inserter schreiben:

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));

Andere Tipps

Für die ersten, haben Sie Ihre eigene Iterator-Klasse erstellen, die Paare ein Flag, das anzeigt, die innerhalb von Paar Position mit einem container<pair> Iterator

Für die zweite, es ist einfacher, obwohl so allgemein zu sein, wie Sie (Behälter gleichen Typs), die Sie brauchen eine template typedef . Hier ist nur für Vektor:

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

Hier ist, wie man gefälschte Vorlage 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);

Mit dem folgenden Code werden alle Werte drucken, wie erforderlich:

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

Ich würde diese einfache Möglichkeit, lieber als benutzerdefinierten Iterator zu schaffen.

Es gibt keine einfache Möglichkeit, die Iteration der Durchführung Sie wollen, Sie können jedoch einen Blick auf die boost :: iterator_adaptor Bibliothek nehmen möchten oder Ihre eigenen Iterator zu implementieren, es zu tun (es sollte nicht zu komplex sein). Dann wird auf die zweite Frage, können Sie std :: Kopie mit Ihrem neuen Iterator-Adapter verwenden.

Nein, es ist wirklich nicht so etwas für std::pair. Sie könnten mit einem Boost-Tuple stattdessen zu betrachten. Ein Tupel ist ein bisschen wie eine erweiterte Version von std::pair die eine beliebige Anzahl von Elementen (bis zu einer gewissen Grenze, aber in der Regel mindestens 10) ermöglicht, und ermöglicht den Zugriff auf die Elemente so etwas wie ein Vektor / Array als auch (dh Sie können zugreifen die Elemente entweder durch Namen oder Index).

TR1 enthält auch std :: tr1 :: tuple, die eine Teilmenge der Boost-des Tupels ist, aber wenn der Speicher dient, enthält es immer noch den Namen / Index-Funktionalität für Sie fragen.

Edit: beachten Sie, dass in beiden Fällen erfordert die Index-Notation ein Compiler- Konstante für den Index, so können Sie keine (Laufzeit) Schleife schreiben über die Elemente iterieren in ein Tupel - aber man kann mit ein bisschen metaprogramming den Job. Boost-Fusion enthält einiges zu unterstützen, was Sie brauchen würden (durch einen seltsamen Zufall, Tupel Teil der Fusionsbibliothek ist).

An einem gewissen Punkt, den Sie verwenden müssen, zuerst und zweiten , auch wenn Sie Ihre eigene Iterator-Klasse erstellen. Ich glaube nicht, dass es ein Ausweg aus der es (zumindest in einer tragbaren Weise).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top