for_eachは、Non-modifying sequence operationsということになっている。では、たとえばこういうコードは、規格違反なのだろうか。
template < typename Iterator > void f( Iterator first, Iterator last ) { std::for_each(first, last, []( std::iterator_traits<Iterator>::reference value) { value = std::iterator_traits<Iterator>::value_type() ; // 書き換える。 } ) ; }
std::iterator_traits<Iterator>::value_typeは、デフォルトコンストラクタと、コピーコンストラクタを持つものとする。このように、参照で受ければ、for_eachで、イテレーターの指す要素を書き換えることが可能だ。
じつは、規格には、mutable iteratorというものがある。これは、あるイテレーターの変数、iに対して、*iという式が、リファレンスを返すイテレーターのことを指す。その場合、for_eachで、イテレーターの指す要素を書き換えることができるのである。
なぜリファレンスでなければならないのか。それは、こういう事だ。
struct Iterator { int operator *() ; }
このように、operator *()がリファレンスを返さなければ、いくら関数オブジェクトの仮引数をlvalueリファレンスで受けても、書き換えることはできない。
No comments:
Post a Comment