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

### 3113. `polymorphic_allocator::construct()` should more closely match `scoped_allocator_adaptor::construct()`

Section: 20.12.3.3 [mem.poly.allocator.mem] Status: Resolved Submitter: Arthur O'Dwyer Opened: 2018-05-14 Last modified: 2020-09-06

Priority: 3

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

View all issues with Resolved status.

Discussion:

Based on my new understanding of how `uses_allocator` and `is_constructible` are supposed to play together, I think there was a minor defect in the resolution of LWG 2969 "`polymorphic_allocator::construct()` shouldn't pass `resource()`".

The calls to `is_constructible` in 20.12.3.3 [mem.poly.allocator.mem] (10.2), which were added to resolve LWG 2969, are missing an lvalue-qualification to match the lvalue-qualification of the parallel calls in [llocator.adaptor.member] (9.2).

The latter talks about constructibility from `inner_allocator_type&`; the former (after LWG 2969) talks about constructibility from `polymorphic_allocator` with no ref-qualification. But since we are perfect-forwarding `*this` through a tuple of references, we definitely are going to try to construct the target object from a `polymorphic_allocator&` and not from a `polymorphic_allocator`. I believe that the wording in 20.12.3.3 [mem.poly.allocator.mem] (10.2) needs to be updated to make the program ill-formed in cases where that construction is going to fail.

Orthogonally, I believe we need additional `std::move`'s in the sentence following 20.12.3.3 [mem.poly.allocator.mem] (10.8) for two reasons:

- We don't want to copy-construct the user's arguments that came in by-value as part of `x` and/or `y`.

- The value category of the argument to `pair`'s constructor is currently unspecified; it could reasonably be either an xvalue or a prvalue. Adding the `std::move` makes it clearer that we really want it to be an xvalue.

[2018-06-18 after reflector discussion]

Priority set to 3

[2019-02; Kona Wednesday night issue processing]

This was resolved by the adoption of P0591 in San Diego.

Proposed resolution:

This wording is relative to N4750.

1. Edit 20.12.3.3 [mem.poly.allocator.mem] as indicated:

   >     template<class T1, class T2, class... Args1, class... Args2>
   >       void construct(pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);

   > > -9- […]

   > > -10- Effects:: […]

   > > 1. (10.1) — […]

   > > 2. (10.2) — Otherwise, if `uses_allocator_v<T1,polymorphic_allocator>` is `true` and `is_constructible_v<T1, allocator_arg_t, polymorphic_allocator&, Args1...>` is `true`, then `xprime` is `tuple_cat(make_tupletuple<allocator_arg_t, polymorphic_allocator&>(allocator_arg, *this), std::move(x))`.

   > > 3. (10.3) — Otherwise, if `uses_allocator_v<T1, polymorphic_allocator>` is `true` and `is_constructible_v<T1, Args1..., polymorphic_allocator&>` is `true`, then `xprime` is `tuple_cat(std::move(x), make_tupletuple<polymorphic_allocator&>(*this))`.

   > > 4. (10.4) — Otherwise the program is ill formed.

   > > Let `yprime` be a tuple constructed from `y` according to the appropriate rule from the following list:

   > > 1. (10.5) — […]

   > > 2. (10.6) — Otherwise, if `uses_allocator_v<T2, polymorphic_allocator>` is `true` and `is_constructible_v<T2, allocator_arg_t, polymorphic_allocator&, Args2...>` is `true`, then `yprime` is `tuple_cat(make_tupletuple<allocator_arg_t, polymorphic_allocator&>(allocator_arg, *this), std::move(y))`.

   > > 3. (10.7) — Otherwise, if `uses_allocator_v<T2, polymorphic_allocator>` is `true` and `is_constructible_v<T2, Args2..., polymorphic_allocator&>` is `true`, then `yprime` is `tuple_cat(std::move(y), make_tupletuple<polymorphic_allocator&>(*this))`.

   > > 4. (10.8) — Otherwise the program is ill formed.

   > > Then, using `piecewise_construct`, `std::move(xprime)`, and `std::move(yprime)` as the constructor arguments, this function constructs a `pair<T1, T2>` object in the storage whose address is represented by `p`.