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