L'exemple commun des boucles for () basées sur la plage de C++ 11 est toujours simple:
std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 };
for ( auto xyz : numbers )
{
std::cout << xyz << std::endl;
}
Dans ce cas, xyz
est un int
. Mais que se passe-t-il quand nous avons quelque chose comme une carte? Quel est le type de la variable dans cet exemple:
std::map< foo, bar > testing = { /*...blah...*/ };
for ( auto abc : testing )
{
std::cout << abc << std::endl; // ? should this give a foo? a bar?
std::cout << abc->first << std::endl; // ? or is abc an iterator?
}
Lorsque le conteneur traversé est quelque chose de simple, il semble que les boucles for () basées sur l'intervalle nous donneront chaque élément, pas un itérateur. Ce qui est bien ... si c'était un itérateur, la première chose à faire est de le déréférencer de toute façon.
Mais je ne sais pas trop à quoi s'attendre lorsqu'il s'agit d'éléments tels que des cartes et des cartes multiples.
(Je suis toujours sur g ++ 4.4, alors que les boucles basées sur les plages sont en g ++ 4.6+, je n'ai donc pas encore eu l'occasion de l'essayer.)
Chaque élément du conteneur est un map<K, V>::value_type
, qui est un typedef
pour std::pair<const K, V>
. Par conséquent, en C++ 17 ou supérieur, vous pouvez écrire
for (auto& [key, value]: myMap) {
std::cout << key << " has value " << value << std::endl;
}
ou comme
for (const auto& [key, value]: myMap) {
std::cout << key << " has value " << value << std::endl;
}
si vous ne prévoyez pas de modifier les valeurs.
En C++ 11 et C++ 14, vous pouvez utiliser des boucles améliorées for
pour extraire chaque paire séparément, puis extraire manuellement les clés et les valeurs:
for (auto& kv : myMap) {
std::cout << kv.first << " has value " << kv.second << std::endl;
}
Vous pouvez également envisager de marquer kv
variable const
si vous souhaitez une vue en lecture seule des valeurs.
En C++ 17, cela s'appelle liaisons structurées , ce qui permet:
std::map< foo, bar > testing = { /*...blah...*/ };
for ( const auto& [ k, v ] : testing )
{
std::cout << k << "=" << v << "\n";
}
De cet article: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf
for( type-specifier-seq simple-declarator : expression ) statement
est syntaxiquement équivalent à
{
typedef decltype(expression) C;
auto&& rng(expression);
for (auto begin(std::For<C>::begin(rng)), end(std::For<C>::end(rng)); begin != end; ++ begin) {
type-specifier-seq simple-declarator(*begin);
statement
}
}
Ainsi, vous pouvez clairement voir que ce qui est abc
dans votre cas sera std::pair<key_type, value_type >
. Donc, pour imprimer, vous pouvez accéder à chaque élément par abc.first
et abc.second
Si vous souhaitez uniquement afficher les clés/valeurs de votre carte et si vous souhaitez utiliser un boost, vous pouvez utiliser les adaptateurs de boost avec les boucles basées sur la plage:
for (const auto& value : myMap | boost::adaptors::map_values)
{
std::cout << value << std::endl;
}
il y a un boost équivalent :: adapters :: key_values
Si l'opérateur d'attribution de copie de foo and bar est bon marché (par exemple, int, char, pointeur, etc.), vous pouvez procéder comme suit:
foo f; bar b;
BOOST_FOREACH(boost::tie(f,b),testing)
{
cout << "Foo is " << f << " Bar is " << b;
}