私は最近 C++11 をますます使用していることに気付き、以前は反復子を使用していた場所で、可能な限り範囲ベースの for ループを使用しています。
std::vector<int> coll(10);
std::generate(coll.begin(), coll.end(), []() { return rand(); } );
C++03:
for (std::vector<int>::const_iterator it = coll.begin(); it != coll.end(); ++it) {
foo_func(*it);
}
C++11:
for (auto e : coll) { foo_func(e); }
しかし、コレクション要素の型がテンプレート パラメーターの場合はどうなるでしょうか。foo_func()
おそらくオーバーロードされて、複雑な (= コピーにコストがかかる) 型を const 参照で渡し、単純なものを値で渡します:
foo_func(const BigType& e) { ... };
foo_func(int e) { ... };
上記の C++03 スタイルのコードを使用している間は、これほど深く考えたことはありませんでした。私は同じように反復し、const_iterator を逆参照すると const 参照が生成されるため、すべて問題ありませんでした。しかし、C++11 の範囲ベースの for ループを使用すると、const 参照ループ変数を使用して同じ動作を得る必要があります。
for (const auto& e : coll) { foo_func(e); }
auto
そして突然、これが単純な型 (参照を実装するための舞台裏のポインターなど) である場合に不要なアセンブリ命令が導入されないかどうか、もう確信が持てなくなりました。
しかし、サンプル アプリケーションをコンパイルすると、単純な型にはオーバーヘッドがなく、これがテンプレートで範囲ベースの for ループを使用する一般的な方法であることが確認されました。そうでない場合は、boost::call_traits::param_typeが適していたでしょう。
質問:規格に保証はありますか?
(この問題は、実際には範囲ベースの for ループとは関係がないことを認識しています。const_iterators を使用している場合にも発生します。)