samedi 18 juin 2011

g++ 4.6 et C++0x - Range based for

Petit bonus du week-end, g++4.6 débarque sur Debian Wheezy. La principale avancée concerne les "range based for", qui sonnent le glas pour la bonne vielle macro BOOST_FOREACH.

Pour une macro, BOOST_FOREACH était plutôt propre et utile, mais en dehors des détails d'implémentation à s'arracher les cheveux (cherchez un peu si ça vous amuse), elle souffrait de ne pas pouvoir utiliser proprement des déclarations templates, à cause notamment des virgules. Exemple:


#include <vector>
#include <string>
#include <iostream>
#include <boost/foreach.hpp>

int main()
{
std::vector<std::pair<int, std::string> > v =
{std::make_pair(1, "a"),
std::make_pair(2, "b")};

BOOST_FOREACH(const std::pair<int, std::string> & item, v)
{
std::cout << item.first << " - " << item.second << std::endl;
}

return 0;
}

Oh, la belle erreur de compile!

foreach.cpp:12:60: error: macro "BOOST_FOREACH" passed 3 arguments, but takes just 2
foreach.cpp: In function ‘int main()’:
foreach.cpp:12:3: error: ‘BOOST_FOREACH’ was not declared in this scope
foreach.cpp:13:3: error: expected ‘;’ before ‘{’ token

La solution est triviale:

typedef std::pair<int, std::string> ItemT;
BOOST_FOREACH(const ItemT & item, v)
{
std::cout << item.first << " - " << item.second << std::endl;
}

Triviale, mais ennuyeuse. Et non-standard. Et quand bien même utiliser des typedef pour ses types est une bonne idée, l'on on a parfois pas envie. Place donc à la solution 0x:

#include <vector>
#include <string>
#include <iostream>

int main()
{
std::vector<std::pair<int, std::string> > v =
{std::make_pair(1, "a"),
std::make_pair(2, "b")};

for(const std::pair<int, std::string> & item : v)
{
std::cout << item.first << " - " << item.second << std::endl;
}

return 0;
}

C'est pas plus joli?

Entre les range based for et les lambdas, plus aucune raison d'utiliser la macro boost, et presque plus aucune raison d'utiliser une vieille boucle for. L'est pas belle, la vie?

Aucun commentaire: