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:

Post a Comment

You can use some HTML elements, such as <b>, <i>, <a>, also, some characters need to be entity referenced such as <, > and & Your comment may need to be confirmed by blog author. Your comment will be published under GFDL 1.3 or later license with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.