Topic: ?Problems interpreting requirement for std::copy ( 25.2.1)


Author: "kanze" <kanze@gabi-soft.fr>
Date: 10 Sep 2005 04:40:21 GMT
Raw View
std::copy has a requirement that:
    result shall not be in the range [first,last).

What does this mean if the iterators are not the same type?

(In the following, consider that any variable v has a type
std::vector, and any variable l a type std::list.)

If the InputIterator is C::const_iterator, and the
OutputIterator C::iterator, I think that the meaning is pretty
clear.  What about if InputIterator is C::const_iterator, and
OutputIterator is C::reverse_iterator?  I would expect that
something like:
    copy( v.begin() + 3, v.begin() + 8, v.rbegin() + 5 ) ;
is also undefined behavior.

As a first approach, I would expect that something like result
refers to the same object as any of the iterators in the range
[begin, end).  But suppose something like:

    struct Toggle
    {
        bool value ;
        Toogle() : value( false ) {}
        bool operator() { value = ! value ; return value ; }
    } ;

    typedef boost::filter_iterator< Toggle,
                                    std::vector< int >::const_iterator
>
                        I ;
    copy( I( v.begin() , v.begin() + 10 ), I(), v.begin() + 4 ) ;

In this case, v.begin() + 4 refers to an element which is not
designated by any iterator in the range [begin,end) passed to
copy -- unless I've made a mistake in my code, the range
[begin,end) includes the elements with indexes 1, 3, 5, 7 and 9.
not index 4.  On the other hand, with every implementation I
know, copy will assign index 3 to index 5 before reading index 5
to assign it to 6.  I rather suspect that it was not intended to
support this, although the arguments to copy are conform to the
Requires clause in    25.2.1.

Finally, what about something like:

    copy( l.begin(), l.end(), back_inserter( l ) ) ;

I think that, realistically, this will generally result in an
endless loop.  And yet, it requires quite a stretch of the
imagination to say that back_inserter( l ) is in the range of
[l.begin(),l.end()).

(Note that for containers other than list, dereferencing
back_inserter(l) will invalidate the results of an earlier
l.end().  Although I'm not sure where it says so in the
standard, common sense says that doing anything which will
invalidate any iterator in the range [begin,end) makes the
behavior of the function undefined.)

Globally, I think that the wording of the requires clause for
copy needs work.  But I can't really think of any reasonable way
to formulate what common sense tells me should be the
restrictions.  (FWIW, I suspect that other functions are
concerned as well.  I just happened to look at copy as a result
of some postings in fr.comp.lang.c++.)

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]