2009-11-11 9 views

Antwort

12

Es gibt ein Problem, weil es ein Makro ist und daher nicht mit Typen umgehen kann, die Kommas enthalten (Präprozessor weiß nichts über Vorlagen).

Sie können die Variable auch vor der Schleife deklarieren, siehe documentation.

std::map<int, double> my_map; 

//1) 
typedef std::pair<int, double> MyPair; 
BOOST_FOREACH(MyPair p, my_map) { ... } 

//2) 
std::pair<int, double> p; 
BOOST_FOREACH(p, my_map) { ... } 

Edit:

Es gibt eine weitere Komplikation mit std::map insbesondere: die value_type nicht std::pair<Key, Value>, aber std::pair<const Key, Value>.

Wenn Sie also mit dem typedef gehen, eine richtige Art und Weise (und der einzige Weg, wenn Sie eine Referenz in der foreach-Schleife verwenden mögen)

typedef std::pair<const int, double> MyPair; 
//or 
typedef std::map<int, double>::value_type MyPair; 

BOOST_FOREACH(MyPair& ref, my_map) { ... } 

jedoch zu verwenden sind, dass won Funktioniert nicht, wenn Sie eine vor der Schleife deklarierte Variable verwenden möchten, da Sie später keine std::pair<const int, double> Instanz zuweisen können (kann nicht dem Feld const zugewiesen werden). In diesem Fall können Sie nur pair<int, double> als manuelle Boost-Shows verwenden.

+1

Sie wahrscheinlich, dass machen sollte tun: std :: map :: value_type –

+0

auch in C++ 11; BOOST_FOREACH (auto & ref, my_map) {...} –

8

Wenn Sie eine Karte iterieren müssen, ist der einfachste Weg Tupeln zu verwenden, da die richtige bekommen type, um typef zu schreiben, ist mühsam. Hier ist, wie Sie Tupeln verwenden können:

std::map<int, double> my_map; 
int key; 
double value; 
BOOST_FOREACH(boost::tie(key, value), my_map) { ... } 

Nur eine Notiz, werden die Kommas hier arbeiten, weil Klammern um Schlüssel und Wert gesetzt werden. Der Präprozessor versteht nur Kommas und Klammern (und c99 erfordert, dass auch Anführungszeichen verstanden werden). So kann es die <> in std::pair<int, double> nicht analysieren. Wir können jedoch Klammern verwenden, um dem Präprozessor zu helfen. Zum Beispiel, wenn wir aa Funktion haben, die einen Behälter gibt, der so genannt wird:

BOOST_FOREACH(int i, foo<int, int>()) { ... } //This won't compile 

So können wir Klammern um einen Ausdruck platzieren und es wird den Präprozessor helfen:

BOOST_FOREACH(int i, (foo<int, int>())) { ... } //This will compile 

jedoch Im Fall einer Map können wir keine Klammern um die Deklaration platzieren (weil es kein Ausdruck ist). So wird dies nicht funktionieren:

BOOST_FOREACH((std::pair<int, double> p), my_map) { ... } //This won't work 

Weil es in so etwas wie diese (std::pair<int, double> p) = *it bekommt umgewandelt wird, und das ist natürlich falsch ist C++.Aber die Verwendung einer Krawatte funktioniert:

Wir müssen nur Schlüssel und Wert außerhalb der Schleife (wie oben gezeigt) zu deklarieren. Außerdem kann die Schleife aussagekräftigere Namen haben. Sie können key anstelle von p.first und value anstelle von p.second schreiben.

+0

Das Komma zwischen Schlüssel und Wert wird den Präprozessor verwirren. – Ferruccio

+0

@Ferruccio Das Komma zwischen Schlüssel und Wert wird *** NOT *** den Präprozessor wegen der Klammer um Schlüssel und Wert nicht verwirren. Außerdem mache ich dies die ganze Zeit, wenn ich eine Karte iterieren muss. –

+0

Ich hatte keine Ahnung, dass Sie das mit dem Präprozessor machen könnten. – Ferruccio

2

Dies kann dies so einfach sein:

BOOST_FOREACH(auto& p, my_map) { ... } 

die C++ 11-Standard, wird automatisch wie var in C#, wird es

BOOST_FOREACH(std::pair<int, double>& p, my_map) { ... }