This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

### 3157. Allocator `destroy` and fancy pointer operations must be non-throwing

Section: 16.4.4.6 [allocator.requirements] Status: New Submitter: Billy O'Neal III Opened: 2018-09-07 Last modified: 2018-12-16

Priority: 3

View other active issues in [allocator.requirements].

View all other issues in [allocator.requirements].

View all issues with New status.

Discussion:

In annotating things required to be called by `~vector`, Casey pointed out that several operations I guarded with `noexcept` aren't actually mandated by the standard to be `noexcept`. However, the STL, and more specifically here, containers, consider inability to destroy an element an unrecoverable condition. This is evidenced for the whole STL by 16.4.6.13 [res.on.exception.handling]/3 "Every destructor in the C ++ standard library shall behave as if it had a non-throwing exception specification.".

As a result, `allocator::destroy` and fancy pointer operations must be non-throwing for valid input, or the containers don't make any sense. This is obvious for things like `vector::~vector`, but less obviously the containers rely on these guarantees whenever inserting more than one element, etc.

Moreover, we too narrowly specify the domain of the `pointer_traits::pointer_to` requirement in the `Cpp17Allocator` requirements, because any node-based container that uses container-internal sentinel nodes needs to be able to form pointers to said sentinel nodes; that operation must also be non-throwing.

[2018-09 Reflector prioritization]

Set Priority to 3

Proposed resolution:

This wording is relative to N4762.

1. Modify 16.4.4.6 [allocator.requirements], Table 32 "Descriptive variable definitions" as indicated:

   > Table 32 — Descriptive variable definitions
   > Variable | Definition
   > --- | ---
   > `…`
   > `YY` | the type `allocator_traits<Y>`
   > `Z` | an allocator-aware container type (24.2.2.1 [container.requirements.general])
   > `…`
   > `y` | a value of type `XX::const_void_pointer` obtained by conversion from a result value of `YY::allocate`, or else a value of type (possibly `const`) `std::nullptr_t`.
   > `z` | an lvalue of type `Z` such that `z.get_allocator() == a`
   > `r1` | a reference to any member subobject of `z`
   > `n` | a value of type `XX::size_type`.
   > `…`

2. Modify 16.4.4.6 [allocator.requirements], Table 33 "`Cpp17Allocator` requirements" as indicated:

   > Table 33 — `Cpp17Allocator` requirements
   > Expression | Return type | Assertion/note pre-/post-condition | Default
   > --- | --- | --- | ---
   > `…`
   > `pointer_traits< X::pointer >::pointer_to(r)` | `X::pointer` | S same as `p`. Throws: Nothing. |
   > `pointer_traits< X::pointer >::pointer_to(r1)` |  | A value of type `YY::pointer` or `YY::const_pointer` `k` such that `*k` is `r1`. Throws: Nothing. |
   > `…`
   > `a.destroy(c)` | (not used) | Effects: Destroys the object at `c`. Throws: Nothing. | `c->~C()`
   > `…`

3. Modify 16.4.4.6 [allocator.requirements], p5, as indicated:

   > -5- An allocator type `X` shall satisfy the `Cpp17CopyConstructible` requirements (Table 26). The `X::pointer`, `X::const_pointer`, `X::void_pointer`, and `X::const_void_pointer` types shall satisfy the `Cpp17NullablePointer` requirements (Table 30). No constructor, comparison function, copy operation, move operation, or swap operation on these pointer types shall exit via an exception. `X::pointer` and `X::const_pointer` shall also satisfy the requirements for a random access iterator (25.3.5.7 [random.access.iterators]) and of a contiguous iterator (25.3.1 [iterator.requirements.general]) and operations in those requirements shall not exit via an exception so long as resulting iterators are dereferencable or past-the-end.

4. Modify 20.2.9.3 [allocator.traits.members], as indicated:

   >     template<class T>
   >       static void destroy(Alloc& a, T* p);

   > > -6- Effects: Calls `a.destroy(p)` if that call is well-formed; otherwise, invokes `p->~T()`.

   > > -?- Throws: Nothing.