Topic: -1?Q?Re: Problems interpreting requirement f


Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Wed, 14 Sep 2005 05:32:31 GMT
Raw View
Gabriel Dos Reis wrote:
> AlbertoBarbati@libero.it (Alberto Ganesh Barbati) writes:
>
> | kanze wrote:
> | >
> | > 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()).
> |
> | It doesn't result in an endless loop, because l.end() is not
> | re-evaluated during the execution of copy.
>
> the "because" part is irrelevant.  See below.

I think it is, see below.

>
> And James' claim that the l.end() is invalidated is bogus.
>
> | The value which is passed as
> | the "last" parameter remains a valid iterator which keeps pointing to
> | the same element for the whole execution of the algorithm. Therefore the
> | statement will effectively just append a entire copy of l at the end of
> | l itself.
>
> Consider this:
>
>     p = l.end();
>     l.push_back(8);
>     q = l.end();
>     assert (p == q);
>

That might happen for some (probably most) implementations of std::list,
but I could find no statement in the standard that provides such
guarantee. If you think such guarantee is provided, I will be glad to
have a precise reference in the standard. Without an explicit or
implicit guarantee you cannot assume that the expression in the assert
always true for all conformant implementations of std::list.

Alberto

---
[ 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                       ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Wed, 14 Sep 2005 23:23:03 GMT
Raw View
kanze wrote:
> Alberto Ganesh Barbati wrote:
>=20
>>Gabriel Dos Reis wrote:
>=20
>=20
>     [...]
>=20
>>>Consider this:
>=20
>=20
>>>    p =3D l.end();
>>>    l.push_back(8);
>>>    q =3D l.end();
>>>    assert (p =3D=3D q);
>=20
>=20
>>That might happen for some (probably most) implementations of
>>std::list, but I could find no statement in the standard that
>>provides such guarantee. If you think such guarantee is
>>provided, I will be glad to have a precise reference in the
>>standard. Without an explicit or implicit guarantee you cannot
>>assume that the expression in the assert always true for all
>>conformant implementations of std::list.
>=20
>=20
> =A723.2.23/1, in the decription of insert, push_front and
> push_back: "Does not affect the validity of iterators and
> references."
>=20
> I don't find an exact definition in the standard as to what it
> means by validity, but from the actual use, I think it means
> that the iterator continues to designate the same element (or in
> the case of end(), it continues to designate an element one past
> the end).

I agree that the statement means that a valid past-the-end iterator
remains valid after a push_back, but it's not obvious to me that it
should remain a past-the-end iterator. One could implement a
past-the-end iterator in such a way that, after a push_back, it points
to (newly added) last element and I don't see how such implementation
would be violating the standard. Of course I may be missing something.

>=20
> Note that this guarantee only applies to std::list.  The other
> containers offer differents sets of guarantees, and none of the
> other containers guarantee the validity of an end iterator after
> an insertion.
>=20

Correct, I was mistaken to say that it applies to std::deque also,
because push_back invalidate all iterators, in that case.

Alberto

---
[ 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                       ]





Author: squell@alumina.nl (Marc Schoolderman)
Date: Sun, 11 Sep 2005 15:41:14 GMT
Raw View
kanze wrote:

> 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()).

I think this example is different from the others, since the input and
output ranges don't strictly overlap, yet assigning through the output
iterator has the side effect of increasing the input range. This also
means the complexity requirement of copy() gets violated since it will
do more than "exactly last - first assignments" -- unless it measures
"last - first" before it enteres the copy loop, but that would be
inefficient for bidirectional iterators.

> 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.

Perhaps the requirement should be that the output iterator should not
produce any side effects in the range [first, last)? This seems similar
to the requirement that predicates should be side-effect free and I
think covers all of your examples.

~Marc.

---
[ 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                       ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 13 Sep 2005 04:20:46 GMT
Raw View
kanze wrote:
>
> 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()).

It doesn't result in an endless loop, because l.end() is not
re-evaluated during the execution of copy. The value which is passed as
the "last" parameter remains a valid iterator which keeps pointing to
the same element for the whole execution of the algorithm. Therefore the
statement will effectively just append a entire copy of l at the end of
l itself.

> (Note that for containers other than list, dereferencing
> back_inserter(l) will invalidate the results of an earlier
> l.end().

back_inserter can be used only for vector, deque, list and string. Only
vector and string invalidates iterators after a push_back, while both
deque and list don't.

Alberto

---
[ 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                       ]