Topic: Minor modification: nothrow guarantee for clear() in sequence


Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Mon, 6 Aug 2007 03:14:12 GMT
Raw View
Greg Herlihy ha scritto:
>
> I think it would be very confusing to state that non-MoveAssignable objects
> can be cleared from a Standard container - given that non-MoveAssignable
> objects are not permitted to be in any Standard container in the first
> place.
>

Good point. I forgot there is a blanket requirement about T always being
both MoveConstructible and MoveAssignable (shame on me!). As erase() can
be implemented using MoveAssignable only, defining clear() through
erase() is not imposing any requirement T mustn't already have. The
"second goal" described in my previous post is therefore already
achieved with the current draft wording, we don't need any change for that.

By the way, I missed this phrase in the "Complexity" paragraph: "the
move assignment operator of T is called the number of times equal to the
number of elements in the vector after the erased elements." This phrase
already guarantees that no elements are moved/copied when the last ==
end(), so it seems that the current draft wording already achieves also
goal number 1 (i.e.: the no-throw guarantee for clear()), without
modifications.

Ganesh

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: Michael DOUBEZ <michael.doubez@free.fr>
Date: Tue, 31 Jul 2007 09:18:42 CST
Raw View
James Kanze a    crit :
> On Jul 23, 4:28 pm, Michael DOUBEZ <michael.dou...@free.fr> wrote:
>
>> * Section 23.1.1/4, 23.1.2/7, 21.3.4/13
>
>> The clear() member function in sequence container is said to be
>> equivalent to:
>
>> "erase(begin(), end())"
>
>> Or erase() is nothrow only if the copy and assignment operator do not
>> throw an exception. The standard is not explicit whether or not clear()
>> is also nothrow except in the case of list modifier in 23.2.3.3/4
>
>> "4. Throws: Nothing."
>
>> *Proposed Resolution:
>
>> Replace "erase(begin(), end())" by "Erases all elements in the
>> container" in the mentionned occurences.
>
> That's considerably less precise.  The current wording
> guarantees that clear() has all of the same semantics as erase
> (e.g. with regards to iterator validity, etc.)

I am not familair with this kind of issue. Since clear() erases all
elements I would have thought all iterators would be invalidated; or is
it your point that all the wordings would have to be duplicated ?

>
>> * Rationale:
>
>> In the case of erase(begin(), end()) no copy or assignment operation is
>> likely to take place. Thus clear() is not expected to throw.
>
> A better solution would probably be to specify explicitly in
> erase that if the first iterator is begin(), and the second
> end(), neither the copy constructor nor the assignment operator
> will be called.  I don't normally like such special cases, but
> in this case, I suspect that there is some justification for it.

Without modifying the requierements on erase() in order to retain the
erase() guarantees,    23.1/10 could be change
* from: (10  Unless otherwised specified ...)
- no erase(), pop_back() or pop_front() function throws an exception

* to (10  Unless otherwised specified ...):
- no erase(), clear(), pop_back() or pop_front() function throws an
exception


Michael DOUBEZ

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Sat, 4 Aug 2007 15:24:17 GMT
Raw View
David Abrahams ha scritto:
>=20
> It would be pretty easy to make a backwards-compatible, nonthrowing
> clear.  In fact, I'm willing to bet that every single implementation
> of clear is already nonthrowing in practice.  We just need the
> standardese to bless that.  Then I'd like to go one step further and
> lift the move/copy ctor requirement.  None of these changes could
> possibly have an effect on program semantics unless the standard
> library implementation had perverted implementation of erase that
> needlessly copied elements.
>=20

Allow me to recap. All references are relative to the latest draft
N2315, 23.1/10 says that:

"Unless otherwise specified (see 23.2.2.3 and 23.2.5.4) all container
types defined in this clause meet the following additional requirements:
=E2=80=94 [...]
=E2=80=94 no erase(), pop_back() or pop_front() function throws an except=
ion.
- [...]"

The 23.2.2.3 and 23.2.5.4 clauses mention erase() in these terms:

"Throws: Nothing unless an exception is thrown by the copy constructor
or assignment operator of T."

Then, we have table 88 that defines clear() in terms of erase(begin(),
end()).

Finally, 23.2.3.3 makes list special, by requiring the no-throw
guarantee explicitly for clear().

Now we have two goals:

1) expressing a no-throw guarantee for deque::clear() and vector::clear()

2) lift the move/copy requirements from deque::clear() and
vector::clear() (as we will see below, there are no such requirement for
list::clear(), right now)

There are many ways to achieve that, of course. I'm pretty sure we can
find a solution that doesn't break existing code.

The first thing that comes to my mind is: erase() can throw only when
calling copy constructors or assignment operators, so what if it doesn't
call any? It could not throw then! But when does erase() actually need
to call them? For a vector, that happens if and only if last !=3D end().
For a deque if and only if first !=3D begin() and last !=3D end(). The
requirements for the invalidation of references implicitly mandate that.
 So why not state the requirement explicitly? For example, for vector,
we could change 23.2.5.2/5 from

"Effects: Invalidates iterators and references at or after the point of
the erase."

to

"Effects: Invalidates iterators and references at or after the point of
the erase. If position =3D=3D end() or last =3D=3D end() no element is co=
pied."

Similarly for deque. This will quickly and easily get rid of goal number
1 as well as being a useful clarification on erase().

Before considering goal number 2, let me point your attention to the
fact that, currently, Table 88 puts *no* requirements on T for both
methods erase() and clear(). I guess that's because for list there are
no such requirements, but somehow they are missing even for vector and
deque in the full specifications of those containers! Of course we know
that vector::erase() and deque::erase() can't be implemented without at
least CopyAssignable or MoveAssignable (we don't actually need
CopyContructible nor MoveConstructible, I think). I think the standard
might specify this fact more explicitly. This can be done by simply
adding in the specifications of erase() in 23.2.2.3 and 23.2.5.4 a new
paragraphs like:

"Requires: T shall be CopyAssignable or MoveAssignable."

Back to goal number 2, one simple solution might be to provide a full
specification clear() in addition to table 88, in line with:

"void clear();

Requires: Despite clear() is defined in terms of erase(), T need not be
CopyAssignable or MoveAssignable.
Effects: as if erase(begin(), end()).
Throws: nothing."

The "as if" takes care that the semantic remains the same as the current
standard, but without imposing unneeded requirements on T.

Any comments?

Ganesh

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: greghe@pacbell.net (Greg Herlihy)
Date: Sun, 5 Aug 2007 00:44:10 GMT
Raw View


On 8/4/07 8:24 AM, in article RqZsi.80579$%k.222457@twister2.libero.it,
"Alberto Ganesh Barbati" <AlbertoBarbati@libero.it> wrote:
>
> "void clear();
>
> Requires: Despite clear() is defined in terms of erase(), T need not be
> CopyAssignable or MoveAssignable.
> Effects: as if erase(begin(), end()).
> Throws: nothing."
>
> The "as if" takes care that the semantic remains the same as the current
> standard, but without imposing unneeded requirements on T.
>
> Any comments?

I think it would be very confusing to state that non-MoveAssignable objects
can be cleared from a Standard container - given that non-MoveAssignable
objects are not permitted to be in any Standard container in the first
place.

Greg

---
[ 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.comeaucomputing.com/csc/faq.html                      ]