Topic: Defect Report: Comparing forward_list::before_begin() to forward_list::end()


Author: Joe Gottman <josephgottman@comcast.net>
Date: Sun, 13 Mar 2011 09:55:43 CST
Raw View
For an object c of type forward_list<X, Alloc>, the iterators
c.before_begin() and c.end() are part of the same underlying sequence,
so the expression c.before_begin() == c.end()  must be well-defined.
But the standard says nothing about what the result of this expression
should be.  The forward_iterator requirements says no dereferenceable
iterator is equal to a non-dereferenceable iterator and that two
dereferenceable iterators are equal if and only if they point to the
same element.  But since before_begin() and end() are both
non-dereferenceable, neither of these rules applies.

   Many forward_list methods, such as insert_after(), have a
precondition that the iterator passed to them must not be equal to
end().  Thus, user code might look like the following:

    void foo(forward_list<int> &c, forward_list<int>::iterator it)
    {
        assert(it != c.end());
        c.insert_after(it, 42);
    }

    Conversely, before_begin() was specifically designed to be used with
methods like insert_after(), so if c.before_begin() is passed to this
function the assertion must not fail.



Proposed Resolution:
    Add to the definition of forward_list::before_begin() (23.3.3.2)
Remarks: before_begin() == end() shall equal false.


Joe Gottman


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Mon, 14 Mar 2011 12:45:28 CST
Raw View
[First submission failed]

On 2011-03-13 16:55, Joe Gottman wrote:
>
> For an object c of type forward_list<X, Alloc>, the iterators
> c.before_begin() and c.end() are part of the same underlying sequence,
> so the expression c.before_begin() == c.end() must be well-defined.
> But the standard says nothing about what the result of this expression
> should be. The forward_iterator requirements says no dereferenceable
> iterator is equal to a non-dereferenceable iterator and that two
> dereferenceable iterators are equal if and only if they point to the
> same element. But since before_begin() and end() are both
> non-dereferenceable, neither of these rules applies.
>
> Many forward_list methods, such as insert_after(), have a
> precondition that the iterator passed to them must not be equal to
> end(). Thus, user code might look like the following:
>
> void foo(forward_list<int> &c, forward_list<int>::iterator it)
> {
> assert(it != c.end());
> c.insert_after(it, 42);
> }
>
> Conversely, before_begin() was specifically designed to be used with
> methods like insert_after(), so if c.before_begin() is passed to this
> function the assertion must not fail.
>
> Proposed Resolution:
> Add to the definition of forward_list::before_begin() (23.3.3.2)
> Remarks: before_begin() == end() shall equal false.

I agree with your observation and would add that your suggested change
is necessary, but not sufficient. Since we have no implied meaning for
cbefore_begin() (as we have for cbegin() due to Table 96), it is also
necessary to complete your suggested remark by adding an operational
semantics, e.g.

"The effects of cbefore_begin() are equivalent to
const_cast<forward_list const&>(*this).before_begin()"

Your observation also reveals another defect in the iterator
requirement tables: The current pre-condition for the expression

++r

in Table 107 "Input iterator requirements" is

pre: r is dereferenceable.

This is an unnecessary overspecification on the one side and an
underspecification on the other and in fact leads to the problem how
it should be possible to increment the result of before_begin() [There
are some other misses in the iterator requirement tables, but this one
was not on my list until you reported the before_begin() specification
problem]. The fix should be to change this pre-condition to

pre: r is incrementable.

and to define the term "incrementable" properly (it is lacking).

Greetings from Bremen,

- Daniel Kr   gler


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]