2016-07-21 8 views
10

glaube, ich habe 2 (oder mehrere) Behälter I gleichzeitig durch iterieren wollen - beispielsweise das Skalarprodukt zweier Vektoren zu berechnen:Bereich für Schleife mit mehreren Behältern

std::vector<double> vector1; 
std::vector<double> vector2; // identical size to vector1 

Was die C + bevorzugt ist +11 Möglichkeit, eine Range-for-Schleife über beide (oder alle) Container gleichzeitig zu spezifizieren? Beinhaltet es die Auswahl eines Containers/Iterators, um Short-Hand (d. H. for (auto i : c)) in eine Range-for-Schleife zu schreiben, während alle anderen Container/Iteratoren lang- hand gehandhabt werden müssen? Gibt es einen Grund die Syntax in Zukunft nicht kurz Hand für beide/alle Container erweitert werden könnten, um Unterstützung, wie unten gezeigt ... die wirklich lesbar scheint:

double dotProduct(0.0); 
for (auto const & value1 : vector1, auto const & value2 : vector2) // illegal! 
{ 
    dotProduct += value1*value2; 
} 
+3

Mögliche Duplikate 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 -mehr-containers-simultan) – ildjarn

+0

Auf der Oberfläche, ja ... aber sind irgendwelche der Antworten dort (a) lesbar und (b) allgemein und (c) basierend auf Standard-C++? Nicht, dass ich es gesehen hätte. Von den frühen Tagen von C an könnte man schreiben "für (i = 0, j = 0, k = 0; i omatai

+0

Werfen Sie einen Blick auf [Miterator] (https://github.com/ClaasBontus/iterator). Es wird alles einfacher werden mit Bereichen, die nicht vor C++ 20 sein werden. –

Antwort

7

In anderen (oft funktional) Sprachen dies geschehen ist mit einer Funktion namens zip. Als Beispiel hat Python eine eingebaute Reißverschluss, der über seine Argumente iteriert und gibt ein Tupel:

for i in zip([1,2,3], (1,2,3), { 0:0, 1:1, 2:2 }): 
    l,t,d = i 
    print("list item: %d, tuple item %d, dict item %d" % (l,t,d))  

Sie eine Reihe Bibliothek in C++ verwenden können, um diese Funktionalität zu erhalten, z.B. Boost.Range oder Eric Niebler's rangev3. Bereiche wurden leider nicht in der C++ 17 Standard gewählt, aber ich würde nie ein Projekt ohne eine Bereichsbibliothek starten.

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

int main(int, const char*[]) 
{ 
    std::vector<int> const v{0,1,2,3,4}; 
    std::list<char> const l{'a', 'b', 'c', 'd', 'e'}; 

    for(auto const& i: boost::combine(v, l)) 
    { 
     int ti; 
     char tc; 
     std::tie(ti,tc) = i; 
     std::cout << '(' << ti << ',' << tv << ')' << '\n'; 
    } 

    return 0; 
} 

Mit C 17 ++ Sie die std::tie mit strukturierter Bindung ersetzen können, und entfernen Sie die Art der ungewöhnlichen „Initialisierung“ mit std::tie: In Boost.Range wird die Funktion combine genannt.

for(auto const& [ti,tc] : boost::combine(v, l)) { 
    std::cout << '(' << ti << ',' << tv << ')' << '\n'; 
    } 

Während ich bedauere, dass Bereiche C 17 ++ nicht enthalten in, ich glaube, dass strukturierte Bindungen ein großer Fortschritt und wird ernsthaft die Möglichkeit, Code ändern geschrieben wird. Bereiche im Standard zu haben, würde sie populärer machen und sie aus einer Bibliothek eines Drittanbieters herausheben, wo viele Leute Einwände haben, weil es etwas ist, was sie nicht zu einem Standardmerkmal wissen, das C++ - Programmierer wissen sollten.

+0

Eine vollkommen gültige Antwort ... aber ein bisschen enttäuschend. Und sollte es nicht 'std :: tie (ti, tc) = i' sein? Was ich daran unbefriedigend finde, ist nicht deine Schuld - es ist der Fehler der C++ - Syntax, die stark auf (a) das Kombinieren von Dingen mit (b) Tricks und (c) einem einzelnen Iterator ... anstatt (einfacheren) mehreren synchronisierten Iteratoren steuert . Angesichts der ursprünglichen C-Syntax, die in meinem Kommentar zu meiner Frage gezeigt wird, bin ich überrascht, dass C++ 'for nicht unterstützt (int i = 0, int j = 0; ...)' wenn (int i = 0, j = 0; ...) '. Ich bin gespannt, ob es einen zwingenden Grund gibt, warum nicht. – omatai

+0

@omatai warum enttäuschend? Sie können boost :: combine sogar in C++ 98 Code verwenden. In Bezug auf "Tricks" - siehe Python-Version - gibt es auch "Trick" zum Kombinieren von Dingen, sogar Haskell hat Zip "Trick".Und ich glaube nicht, dass das ein Nachteil ist - warum sollte man die Sprache mit Dingen verunreinigen, die leicht in Bibliotheken implementiert werden können? –

+0

Lesbarkeit, Unordnung. Wenn ich in fünf Jahren entweder auf meinen vorgeschlagenen (illegalen) Code oder diesen Code stieß, würde ich sofort wissen, was mit meinem Vorschlag vor sich ging, und ich musste viel mehr Geisteskraft und Glaubenssprünge anwenden, um dies zu verdauen (absolut gültig). Version (keine Beleidigung für @Jens). Ich bin also nicht enttäuscht von dieser (durchaus gültigen) Antwort, sondern vom Versagen der C++ - Syntax, etwas zu unterstützen, was meiner Meinung nach einfacher und sauberer wäre. – omatai

Verwandte Themen