2014-03-03 5 views
11

Ich brauche einen Ratschlag für die folgende Situation - Ich kann es nicht stundenlang herausfinden: Wie man durch mehr als eine Seq durchgeht. Container der gleichen Größe (hier: zwei Vektoren) auf einfache Weise?Iterieren über mehr als eine Seq. Container in C++ 11

int main() { 
    int size = 3; 
    std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 }; 

    // old-fashioned - ok 
    for (int i = 0; i < size; i++) { 
    std::cout << v1[i] << " " << v2[i] << std::endl; 
    } 

    // would like to do the same as above with auto range-for loop 
    // something like this - which would be fine for ONE vector. 
    // But this does not work. Do I need a hand-made iterator instead? 
    for (const auto& i:v1,v2) { 
    std::cout << i << " " << i << std::endl; 
    } 

    return EXIT_SUCCESS; 
} 

Vielen Dank!

+0

Zuerst dachte ich, es ist ein Betrogener, aber es scheint nicht so. –

+0

mögliches Duplikat von [Was ist der beste Weg, um über zwei oder mehr Container gleichzeitig zu iterieren] (http://stackoverflow.com/questions/12552277/whats-the-best-way-to-iterate-over-two-or-more -containers-simultan) – TemplateRex

Antwort

13

Die range-basierte for-Schleife wurde als ein Vorteil für die Iteration einer Reihe entwickelt, weil es bei weitem der häufigste Fall ist. Wenn Sie mehrere Bereiche durchlaufen müssen, die nicht, dass die häufigste Fall ist, können Sie es immer noch die traditionelle Art und Weise tun:

for (auto i1 = begin(v1), i2 = begin(v2), e = end(v1); i1 != e; ++i1, ++i2) 
{ 
    // processing 
} 
+2

+1 ... nicht alles muss in ein bestimmtes Sprachfeature geschärft werden. Die Evolution von C++ legt besonderen Wert auf nützliche Funktionen, die gut zusammenarbeiten; Ein neues Feature verdrängt kein anderes, sondern alle arbeiten daran, die Sprache besser zu machen. –

+0

Es gibt tatsächlich eine aktive Anfrage in der Core Language Arbeitsgruppe, um die Syntax zu unterstützen, um gleichzeitig auf vielen Sequenzen mit bereichsbasierten for-Schleifen zu iterieren, also ist dies überhaupt nicht weit hergeholt (aber eindeutig nicht für C++ 14), siehe http://cplusplus.github.io/EWG/ewg-active.html#43 –

+3

Sollte es nicht sein? e1 = Ende (v1), e2 = Ende (v2); i1! = e1 && i2! = e2'? Ich erkenne in diesem Fall, dass die beiden Vektoren zufällig die gleiche Länge haben, aber sollte die 'for' -Schleife geschrieben werden, um davon abhängig zu sein? –

13

Es gibt boost::combine() in Boost.Range, die ein

#include <iostream> 
#include <iterator> 
#include <vector> 
#include <boost/range/combine.hpp> 

int main() 
{ 
    std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 }; 

    for (auto&& t : boost::combine(v1, v2)) 
      std::cout << t.get<0>() << " " << t.get<1>() << "\n";  
} 

schreiben können Live Example .

Wenn Sie nicht auf diese verlassen möchten, können Sie die combine() Funktionalität sich mit Boost.Iterator ‚s zip_iterator und Boost.Range‘ buchstabieren s iterator_range und ein wenig von C++ 14 hergeleitete Rück Typen:

template<class... Ranges> 
auto combine(Ranges const&... ranges) 
// add -> decltype(boost::make_iterator_range(...)) in C++11 
{ 
    return boost::make_iterator_range(
     boost::make_zip_iterator(boost::make_tuple(begin(ranges)...)), 
     boost::make_zip_iterator(boost::make_tuple(end(ranges)...))   
    ); 
} 

Live Example.

Erklärung: boost::make_zip_iterator schafft eine boost::tuple von Iteratoren in die Eingangsbereiche, und Überlastungen alle üblichen operator++ und operator*, die Sie kennen und lieben von regelmäßigen Iteratoren. Die iterator_range schließt dann zwei dieser zip_iterator s in ein Paket mit einer begin() und end() Funktion, die es von der C++ 11 Range-for-Schleife verwendet werden können. Es verallgemeinert sich auch auf mehr als zwei Eingabebereiche. Sie können das K-te Element aus einem Tupel mit der Elementfunktion entpacken.

+1

Ah, Boost ... "vereinfacht" seit 1999 den Code :-) –

+0

@KerrekSB mit 'iterator_range' können Sie die meisten Komplexitäten ausblenden und auch die Range-for-Schleife verwenden. Für Tupel mit mehreren Bereichen denke ich, es ist ein Nettogewinn, aber ich denke, das ist eine Frage des Geschmacks für Sie. – TemplateRex

+2

Nun, ich sehe den Verdienst, und ein ZIP-Iterator (oder Bereich) ist etwas sehr fundamentales, das wirklich existieren sollte.Ich wünschte nur, du könntest es buchstabieren wie 'beginnen (v1, v2)' oder so ... –