Title
Inconsistent exception guarantees between ordered and unordered associative containers
Status
cd1
Section
[container.requirements][unord.req.except]
Submitter
Ion GaztaƱaga

Created on 2007-12-22.00:00:00 last changed 171 months ago

Messages

Date: 2010-10-21.18:28:33

Proposed resolution:

Create a new sub-section of [associative.reqmts] (perhaps [associative.req.except]) titled "Exception safety guarantees".

1 For associative containers, no clear() function throws an exception. erase(k) does not throw an exception unless that exception is thrown by the container's Pred object (if any).

2 For associative containers, if an exception is thrown by any operation from within an insert() function inserting a single element, the insert() function has no effect.

3 For associative containers, no swap function throws an exception unless that exception is thrown by the copy constructor or copy assignment operator of the container's Pred object (if any).

Change [unord.req.except]p1:

For unordered associative containers, no clear() function throws an exception. No erase(k) function does not throws an exception unless that exception is thrown by the container's Hash or Pred object (if any).

Change [container.requirements] p10 to add references to new sections:

Unless otherwise specified (see [deque.modifiers], and [vector.modifiers], [associative.req.except], [unord.req.except]) all container types defined in this clause meet the following additional requirements:

Change [container.requirements] p10 referring to swap:

  • no swap() function throws an exception unless that exception is thrown by the copy constructor or assignment operator of the container's Compare object (if any; see [associative.reqmts]).
Date: 2007-12-22.00:00:00

[container.requirements]p10 states:

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:

  • [...]
  • no erase(), pop_back() or pop_front() function throws an exception.

[deque.modifiers] and [vector.modifiers] offer additional guarantees for deque/vector insert() and erase() members. However, [container.requirements] p10 does not mention [unord.req.except] that specifies exception safety guarantees for unordered containers. In addition, [unord.req.except] p1 offers the following guaratee for erase():

No erase() function throws an exception unless that exception is thrown by the container's Hash or Pred object (if any).

Summary:

According to [container.requirements] p10 no erase() function should throw an exception unless otherwise specified. Although does not explicitly mention [unord.req.except], this section offers additional guarantees for unordered containers, allowing erase() to throw if predicate or hash function throws.

In contrast, associative containers have no exception safety guarantees section so no erase() function should throw, including erase(k) that needs to use the predicate function to perform its work. This means that the predicate of an associative container is not allowed to throw.

So:

  1. erase(k) for associative containers is not allowed to throw. On the other hand, erase(k) for unordered associative containers is allowed to throw.
  2. erase(q) for associative containers is not allowed to throw. On the other hand, erase(q) for unordered associative containers is allowed to throw if it uses the hash or predicate.
  3. To fulfill 1), predicates of associative containers are not allowed to throw. Predicates of unordered associative containers are allowed to throw.
  4. 2) breaks a widely used programming pattern (flyweight pattern) for unordered containers, where objects are registered in a global map in their constructors and unregistered in their destructors. If erase(q) is allowed to throw, the destructor of the object would need to rethrow the exception or swallow it, leaving the object registered.
History
Date User Action Args
2010-10-21 18:28:33adminsetmessages: + msg3702
2007-12-22 00:00:00admincreate