Title
LWG 3038 and 3190 have inconsistent PRs
Status
c++20
Section
[mem.poly.allocator.mem]
Submitter
Casey Carter

Created on 2019-07-18.00:00:00 last changed 45 months ago

Messages

Date: 2020-02-14.06:55:06

Proposed resolution:

This wording is relative to N4820.

  1. Modify [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)));
      
Date: 2020-02-14.06:55:06

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

Date: 2019-07-29.16:31:34

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. [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.

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2020-02-24 16:02:59adminsetstatus: immediate -> wp
2020-02-14 06:55:06adminsetmessages: + msg11092
2020-02-14 06:55:06adminsetstatus: new -> immediate
2019-07-28 15:43:50adminsetmessages: + msg10521
2019-07-18 00:00:00admincreate