Boost/Alkioiden läpikäynti
Säiliön alkioiden läpikäynti on yksi toistuvimmista ohjelmointi-idiomeista, mutta C++:n for-lauseella se on kovin hankalaa. Uudemmissa ohjelmointikielissä, kuten Javassa ja C#:ssa, siihen on oma foreach-lauseensa. Boostissa on sitä muistuttava makro BOOST_FOREACH
.
Ongelma
muokkaaC++:ssa on vaikeaa ja virhealtistakin läpikäydä säiliön alkiot for-lauseella. Seuraava on väärin, sillä int
ei välttämättä riitä esittämään kaikkia säiliön indeksejä:
// mitä jos vec.size() > std::numeric_limits<int>::max()? for (int i = 0; i < vec.size(); ++i) { std::cout << vec[i]; }
Seuraava on oikein ja vastaava toimii vektoreiden lisäksi myös muilla säiliöillä:
for (std::vector<char>::iterator i = vec.begin(); i != vec.end(); ++i) { std::cout << *i; }
On kuitenkin huonoa tyyliä määritellä jonkin säiliön tyyppi useammassa kuin yhdessä paikassa, koska tällöin sitä on vaikeampi vaihtaa jälkeenpäin. Niinpä usein luodaan alias oikealle tyypille:
typedef std::vector<char> CharContainer; CharContainer cc; ... for (CharContainer::iterator i = cc.begin(); i != cc.end(); ++i) { std::cout << *i; }
On selvää, että tällainen ratkaisu on hidas kirjoittaa ja lukea.
Ratkaisu
muokkaaBoostissa on helppokäyttöinen makro säiliön alkioiden läpikäyntiin:
#include <boost/foreach.hpp> ... BOOST_FOREACH (char c, cc) { std::cout << *c; }
Se on selkeämpi lukea ja helpompi kirjoittaa kuin perinteinen C++-vastineensa.
Huomioitavaa
muokkaaTulee muistaa, että BOOST_FOREACH
on vain makro. Seuraava koodi ei käänny, koska makro luulee pilkun olevan väärässä paikassa:
BOOST_FOREACH (std::pair<int, char> p, map) { std::cout << p.first << "," p.second << std::endl; }
Ratkaisu on luoda alias:
typedef std::pair<int, char> IntCharPair;
Vaihtoehtoisesti voi suosiolla käyttää perinteistä läpikäyntitapaa.