Title
polymorphic_allocator::construct() should more closely match scoped_allocator_adaptor::construct()
Status
resolved
Section
[mem.poly.allocator.mem]
Submitter
Arthur O'Dwyer

Created on 2018-05-14.00:00:00 last changed 63 months ago

Messages

Date: 2019-02-21.17:23:36

Proposed resolution:

This wording is relative to N4750.

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

Date: 2019-02-21.17:23:36

[ 2019-02; Kona Wednesday night issue processing ]

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

Date: 2018-06-18.00:00:00

[ 2018-06-18 after reflector discussion ]

Priority set to 3

Date: 2018-05-14.00:00:00

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 [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 allocator.adaptor.members (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 [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 [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.

History
Date User Action Args
2019-02-21 17:23:36adminsetmessages: + msg10317
2019-02-21 17:23:36adminsetstatus: new -> resolved
2018-06-19 05:49:11adminsetmessages: + msg9950
2018-05-19 19:47:24adminsetmessages: + msg9853
2018-05-14 00:00:00admincreate