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

### 3237. LWG 3038 and 3190 have inconsistent PRs

Section: 20.4.3.3 [mem.poly.allocator.mem] Status: C++20 Submitter: Casey Carter Opened: 2019-07-18 Last modified: 2021-02-25

Priority: 2

View all other issues in [mem.poly.allocator.mem].

View all issues with C++20 status.

Discussion:

Both LWG 3038 and LWG 3190 deal with how to respond to requests to allocate "`n * sizeof(T)`" bytes of memory when `n * sizeof(T)` is not sufficient storage for `n` objects of type `T`, i.e., when `n > SIZE_MAX / sizeof(T)`. LWG 3038 changed `polymorphic_allocator::allocate` to throw `length_error` upon detecting this condition, whereas LWG 3190 changed `allocator::allocate` to throw `bad_array_new_length`. It's peculiar that two standard library components which allocate memory both detect this condition but handle it by throwing different exception types; for consistency, the two should be harmonized.

Reflector discussion of 3190 seemed to achieve consensus that `bad_array_new_length` was the better option. Unlike `length_error`, `bad_array_new_length` derives from `bad_alloc` so we can make this change without altering the invariant that allocation functions either succeed or throw an exception derived from `bad_alloc`.

Further, P0339R6 "`polymorphic_allocator<>` as a vocabulary type" recently added the function template "`template<class T> T* allocate_object(size_t n = 1);`" to `std::pmr::polymorphic_allocator`, which is another instance of the "allocate memory for `n` objects of type `T`" pattern. 20.4.3.3 [mem.poly.allocator.mem] paragraph 8.1 specifies that `allocate_object` throws `length_error` when `SIZE_MAX / sizeof(T) < n`, presumably for consistency with `std::pmr::polymorphic_allocator::allocate` specified in paragraph 1. `allocate_object`'s behavior should be consistent with `allocator::allocate` and `polymorphic_allocator::allocate` so we have a single means of communicating "request for allocation of unrepresentable size" errors in the Standard Library.

[2020-02 Moved to Immediate on Thursday afternoon in Prague.]

Proposed resolution:

This wording is relative to N4820.

1. Modify 20.4.3.3 [mem.poly.allocator.mem] as indicated:

   >     [[nodiscard]] Tp* allocate(size_t n);

   > > -1- Effects: If `SIZE_MAX / sizeof(Tp) < n`, throws `length_errorbad_array_new_length`. Otherwise equivalent to:

   > > >     return static_cast<Tp*>(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp)));

   > […]

   >     template<class T>
   >       T* allocate_object(size_t n = 1);

   > > -8- Effects: Allocates memory suitable for holding an array of `n` objects of type `T`, as follows:

   > > 1. (8.1) — if `SIZE_MAX / sizeof(T) < n`, throws `length_errorbad_array_new_length`,

   > > 2. (8.2) — otherwise equivalent to:

   > >    >     return static_cast<T*>(allocate_bytes(n*sizeof(T), alignof(T)));