2016-04-07 14 views
1

Ich habe eine Funktion, die zwei ganzzahlige Vektoren dauert. Der erste Vektor wird als Referenz übergeben, der zweite als Verweis auf eine Konstante. Ich möchte beide Vektoren gleichzeitig durchlaufen und den ersten Vektor aktualisieren. So etwas wie die folgende Liste:Iterieren gleichzeitig über ref/cref Bereiche

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

void foo(std::vector<int>& a, std::vector<int> const& b) 
{ 
     boost::tuple<int&, int const&> x; 
     BOOST_FOREACH(x, boost::combine(a,b)) { 
      int& v1 = x.get<0>(); 
      int const& v2 = x.get<1>(); 
      v1 = v1 + v2 + 5; 
     } 

} 

int main(int argc, char **argv) 
{ 
    std::vector<int> a(3,10); 
    std::vector<int> b(3,10); 

    foo(a,b); 
    for (int v : a) { 
    std::cout << v << std::endl; 
    } 
    return 0; 
} 

Das Problem, das ich in laufen lasse sich auf zwei Bereiche laufen, wo man ref ist und das andere ist ref konst. Wie funktioniert das richtig mit boost: combine/for loop? Vielen Dank.

+1

Warum Sie Ihre Frage tagge C++ 11 und Verwenden Sie das Boost-Tupel und foreach? – Chiel

+0

Und warum überliefern Sie die zweite als eine konstante Referenz? – Chiel

+0

Und drittens, können Sie einen Code setzen, den wir tatsächlich kompilieren und ausführen können? Oder im schlimmsten Fall, dass wir bearbeiten können, damit es kompilieren kann? – Chiel

Antwort

1

Sie haben die C++ 11-Typableitung nicht vollständig genutzt. Beim Iterieren über Ganzzahlen ist es sinnlos, auf sie als Referenz zuzugreifen.

Der Grund, warum Ihr Code nicht kompiliert wurde, war zweifach: 1. Sie können ein Tupel nicht mit Referenzen konstruieren, und 2. Sie können seinen Wert nicht ändern, wenn er eine const-Referenz hat. Die boost::tuple<int&, int const&> x; war sowieso nicht nötig.

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

void foo(std::vector<int>& a, std::vector<int> const& b) 
{ 
    for(auto x : boost::combine(a,b)) 
     x.get<0>() += x.get<1>() + 5; 
} 

int main() 
{ 
    std::vector<int> a(3,10); 
    std::vector<int> b(3,10); 
    foo(a,b); 
    for (auto v : a) 
     std::cout << v << std::endl; 
} 

Natürlich kann man wirklich std::transform verwenden sollte, aber dies zeigt, dass der Code funktionieren würde, wenn nur Sie Leveraged C 11 ++ ein bisschen mehr :)

+0

Vielen Dank für Ihre Zeit. Es macht jetzt Sinn. Ich stimme zu, ich würde es nicht mit int verwenden. Tatsächlicher Code verwendet kompliziertere Strukturen, aber ich habe die Problembeschreibung einfach reduziert, um den Vektor von Ints zur Vereinfachung zu verwenden. – user4979733

5

Zumindest, wenn ich die Boost-Sachen richtig gerade lese, scheinen Sie etwas ähnliches wollen:

std::transform(a.begin(), a.end(), 
       b.begin(), 
       a.begin(), 
       [] (int x, int y) { return x + y + 5; }); 

Wie es jetzt aussieht, dies wird ++ 11 C. Wenn Sie es ohne C++ 11 benötigen, können Sie zweifellos Lambda verwenden Erhöhung über die gleiche Sache zu tun, oder Sie können sich eine Funktion Objekt schreiben:

struct combine { 
    int operator()(int x, int y) { return x + y + 5; } 
}; 

void foo(std::vector<int>& a, std::vector<int> const & b) 
{  
    std::transform(a.begin(), a.end(), 
        b.begin(), 
        a.begin(), 
        combine()); 
} 

Beachten Sie auch, dass std::vector<int>& const b falsch ist. Sie haben fast sicher beabsichtigt, stattdessen: std::vector<int> const &b. Mit der constnach die &, heißt es, dass die Referenz selbst const ist. Wenn Sie es vorher verschieben, heißt das, worauf sich die Referenz bezieht: const. Ersteres macht keinen Sinn (Sie können const nicht auf eine Referenz anwenden; in dem Maße, wie das Konzept der const-Referenz überhaupt Sinn ergibt, ist jede Referenz immer const).