386 votes

C++11: comment utiliser la gamme à base de boucle for() avec std::map?

L'exemple le plus connu pour C++0x gamme à base de() les boucles est toujours quelque chose de simple comme ceci:

std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 };
for ( auto xyz : numbers )
{
     std::cout << xyz << std::endl;
}

Auquel cas xyz est int. Mais, ce qui arrive 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 étant traversée est quelque chose de simple, ça ressemble à de la gamme, en fonction de() boucle de nous donner chaque élément, et pas un itérateur. Ce qui est beau...si c'était itérateur, la première chose que nous avons toujours avez à faire est de déréférencement d'elle de toute façon.

Mais je suis confus quant à ce à quoi s'attendre quand il s'agit de choses comme des cartes et des multimaps.

(Je suis toujours sur g++ 4.4, tandis que la gamme de base, les boucles sont en g++ 4.6+, je n'ai pas eu la chance de l'essayer encore.)

575voto

templatetypedef Points 129554

Chaque élément du conteneur map<K, V>::value_type, ce qui est un typedef pour std::pair<const K, V>. Par conséquent, vous devez écrire ce que

for (auto& kv : myMap) {
    std::cout << kv.first << " has value " << kv.second << std::endl;
}

Pour l'efficacité, c'est une bonne idée de faire le paramètre de la boucle de référence. Vous pourriez aussi envisager de faire c' const si vous voulez une vue en lecture seule des valeurs.

26voto

Aditya Kumar Points 3884

À partir de ce document: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf

for( type-specifier-seq simple-declarator : expression ) statement

la syntaxe est équivalente à

{
    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
    }
}

De sorte que vous pouvez clairement voir que ce qui est abc dans votre cas sera std::pair<key_type, value_type >. Donc, pour l'impression, vous pouvez le faire accéder à chaque élément en abc.first et abc.second

16voto

Pixie-Poop Points 21

Si vous souhaitez voir uniquement les clés/valeurs de votre carte et, comme l'utilisation de boost, vous pouvez utiliser le boost adaptateurs de la gamme à base de boucles:

for (const auto& value : myMap | boost::adaptors::map_values)
{
    std::cout << value << std::endl;
}

il y a un équivalent boost::adaptateurs::key_values

http://www.boost.org/doc/libs/1_51_0/libs/range/doc/html/range/reference/adaptors/reference/map_values.html

3voto

balki Points 4786

Si l'opérateur d'assignation de copie de foo et bar est bon marché (par exemple. int, char, etc pointeur), vous pouvez effectuer les opérations suivantes:

foo f; bar b;
BOOST_FOREACH(boost::tie(f,b),testing)
{
  cout << "Foo is " << f << " Bar is " << b;
}

EDIT: ci-dessous ne fonctionne pas comme avant, :, c'est une déclaration, pas une lvalue expression.

foo f;bar b;
for(std::tie(f,b) : testing)
{
   cout << "Foo is " << f << " Bar is " << b;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X