c++ - through - Como usar o loop for() baseado em intervalo com std:: map?




std:: map begin() (4)

O exemplo comum para os loops () de intervalo baseado em C ++ 11 é sempre algo simples como este:

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

Nesse caso, xyz é um int . Mas o que acontece quando temos algo parecido com um mapa? Qual é o tipo da variável neste exemplo:

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

Quando o contêiner sendo percorrido é algo simples, parece que os loops baseados em intervalo for () nos darão cada item, não um iterador. O que é legal ... se fosse um iterador, a primeira coisa que sempre teríamos que fazer é desreferenciando de qualquer maneira.

Mas estou confuso sobre o que esperar quando se trata de coisas como mapas e multimaps.

(Eu ainda estou no g ++ 4.4, enquanto loops baseados no intervalo estão em g + + + + + +, então eu não tive a chance de experimentá-lo ainda.)


A partir deste documento: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf

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

é sintaticamente equivalente a

{
    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-specier-seq simple-declarator(*begin);
        statement
    }
}

Então você pode ver claramente que o que é abc no seu caso será std::pair<key_type, value_type > . Então, para impressão, você pode acessar cada elemento por abc.first e abc.second


Cada elemento do container é um map<K, V>::value_type , que é um typedef para std::pair<const K, V> . Conseqüentemente, você escreveria isso como

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

Para eficiência, é uma boa idéia tornar o parâmetro no loop uma referência. Você também pode considerar torná-lo const se quiser uma visualização somente leitura dos valores.

Começando com C ++ 17, você também pode escrever

for (auto& [key, value]: myMap) {
    std::cout << key << " has value " << value << std::endl;
}

que é muito mais limpo.


Se copiar operador de atribuição de foo e bar for barato (por exemplo, int, char, pointer etc), você pode fazer o seguinte:

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

EDIT : O abaixo não funciona como antes :, tem que ser uma declaração , não uma expressão lvalue .

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





dictionary