2010-02-21

mutable iterator

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: