C++0x の規格制定で、範囲 for 構文をどうするかが議論になっているようです。
本の虫: range-based forに対する意見求む
range-based for の変更案 - Togetter
僕としては、案4の「メンバ関数を呼び出す」が妥当かと思います。
というのも、 ADL というのは非常にタチが悪く、
#include <iostream> namespace A { template<class T> void f( T& x ){ std::cout << "A::f\n"; } class Base {}; } namespace B { class Derived : A::Base {}; void f( Derived const& x ){ std::cout << "B::f\n"; } } int main() { B::Derived x; f(x); }
上記のようなコードがあった場合、殆どの人は正しい動作(http://ideone.com/t3GPF)を予測できないからです。
traits ベースの実装は、標準ライブラリによるサポートが必須である上、
あまり C++ に慣れていない人に、詳細な仕組みを説明するのが面倒です。
しかも public 継承が絡んだ場合、明示的に特殊化しない限り、デフォルトに戻ってしまいます:
#include <iostream> template<class T> struct some_traits { static void invoke( T const& ){ std::cout << "default\n"; } }; template<class T> void f( T const& x ) { some_traits<T>::invoke(x); } struct Base {}; template<> struct some_traits<Base> { static void invoke( Base const& ){ std::cout << "specialized\n"; } }; struct Derived : Base {}; int main() { Base x; f(x); // specialized version Derived y; f(y); // default version }
http://ideone.com/KeSZt
というわけで、初心者には優しくない。
メンバ関数を使えば、そういう問題は一切なくなります。
何より、分かりやすい。これが一番のメリットでしょう。
問題は配列に対して range-based for を使いたい場合で、
その場合は規格上で特別扱いするか、あるいは配列専用のアダプタを作る必要がありますが、
実は現行のドラフトでも、 range-based for に対して配列が渡された場合は、特別扱いすることになっています。
というわけで、その記述をそのまま引き継げばいいだけで、特に問題にはならないでしょう。
何より、メンバ関数を使えば、特に規格を大きく変更すること無く、ADLを排除できます。
これは大きく、例えば traits を使った場合、
その記述をする分だけ、規格に大きな変更が必要になるでしょう。
僕としては、そういうのは嫌です。何故なら、とにかく早く C++0x は確定して欲しいから。
というわけで、僕としては、案4の「メンバ関数によって begin, end を呼び出す」のがいいかな、と思いました。