Title
Comparing forward_list::before_begin() to forward_list::end()
Status
c++11
Section
[forward.list.iter]
Submitter
Joe Gottman

Created on 2011-03-13.00:00:00 last changed 154 months ago

Messages

Date: 2011-03-24.15:58:06

Proposed resolution:

Add to the definition of forward_list::before_begin() [forwardlist.iter] the following:

iterator before_begin();
const_iterator before_begin() const;
const_iterator cbefore_begin() const;

-1- Returns: A non-dereferenceable iterator that, when incremented, is equal to the iterator returned by begin().

-?- Effects: cbefore_begin() is equivalent to const_cast<forward_list const&>(*this).before_begin().

-?- Remarks: before_begin() == end() shall equal false.

Date: 2011-03-24.00:00:00

[ 2011-03-24 Madrid meeting ]

General agreement that this is a serious bug.

Pablo: Any objections to moving 2042 to Immediate?

No objections.

Date: 2011-03-14.00:00:00

[ 2011-03-14: Daniel comments and updates the suggested wording ]

The suggested wording changes are necessary but not sufficient. Since there does not exist an equivalent semantic definition of cbefore_begin() as we have for cbegin(), this still leaves the question open whether the normative remark applies to cbefore_begin() as well. A simple fix is to define the operational semantics of cbefore_begin() in terms of before_begin().

Date: 2011-03-13.00:00:00

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.

History
Date User Action Args
2011-08-23 20:07:26adminsetstatus: wp -> c++11
2011-04-11 11:23:23adminsetstatus: immediate -> wp
2011-03-24 15:58:06adminsetmessages: + msg5684
2011-03-24 15:58:06adminsetstatus: new -> immediate
2011-03-14 22:32:33adminsetmessages: + msg5652
2011-03-13 20:03:22adminsetmessages: + msg5650
2011-03-13 00:00:00admincreate