C++ 11の範囲ベースのfor()ループの一般的な例は、常に次のような単純なものです。
std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 };
for ( auto xyz : numbers )
{
std::cout << xyz << std::endl;
}
その場合xyz
はint
です。しかし、地図のようなものがあるとどうなりますか?この例の変数の型は何ですか:
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?
}
トラバースされるコンテナが単純な場合は、範囲ベースのfor()ループによって、反復子ではなく各項目が返されるように見えます。どれがいいですか...それがイテレータであるならば、私たちがいつもしなければならない最初のことはとにかくそれを間接参照することです。
しかし、私はそれが地図やマルチマップのようなものになるとどうなるかについて混乱しています。
(私はまだg ++ 4.4を使っていますが、範囲ベースのループはg ++ 4.6+に入っているので、まだ試す機会がありませんでした。)
コンテナの各要素はmap<K, V>::value_type
で、これはstd::pair<const K, V>
のtypedef
です。したがって、これを次のように書きます。
for (auto& kv : myMap) {
std::cout << kv.first << " has value " << kv.second << std::endl;
}
効率的には、ループ内のパラメータを参照にすることをお勧めします。値の読み取り専用ビューが必要な場合は、const
にすることも検討できます。
C++ 17以降では、次のように書くこともできます。
for (auto& [key, value]: myMap) {
std::cout << key << " has value " << value << std::endl;
}
これはずっときれいです。
C++ 17では、これは 構造化バインディング と呼ばれ、次のことが可能になります。
std::map< foo, bar > testing = { /*...blah...*/ };
for ( const auto& [ k, v ] : testing )
{
std::cout << k << "=" << v << "\n";
}
この論文から: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf
for( type-specifier-seq simple-declarator : expression ) statement
構文的に同等です
{
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
}
}
ですから、あなたのケースでabc
がstd::pair<key_type, value_type >
になることがはっきりわかります。それで、印刷のためにあなたはabc.first
とabc.second
によって各要素にアクセスすることができます
マップからキー/値のみを表示したい場合や、boostを使用したい場合は、範囲ベースのループでboostアダプタを使用することができます。
for (const auto& value : myMap | boost::adaptors::map_values)
{
std::cout << value << std::endl;
}
同等のboost :: adapters :: key_valuesがある
Fooとbarのコピー代入演算子が安い場合(例:int、char、pointerなど)、次のことができます。
foo f; bar b;
BOOST_FOREACH(boost::tie(f,b),testing)
{
cout << "Foo is " << f << " Bar is " << b;
}