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

### 3821. `uses_allocator_construction_args` should have overload for `pair-like`

Section: 20.2.8.2 [allocator.uses.construction] Status: Open Submitter: Tim Song Opened: 2022-11-08 Last modified: 2022-11-12

Priority: 2

View other active issues in [allocator.uses.construction].

View all other issues in [allocator.uses.construction].

View all issues with Open status.

Discussion:

P2165R4 added a `pair-like` constructor to `std::pair` but didn't add a corresponding `uses_allocator_construction_args` overload. It was in P2165R3 but incorrectly removed during the small group review.

Without LWG 3525, not having the overload would have caused emplacing a `pair-like` into a `pmr::vector<pair>` to be outright ill-formed.

With that issue's resolution, in cases where the constructor is not explicit we would create a temporary pair and then do uses-allocator construction using its pieces, and it still won't work when the constructor is explicit.

We should just do this properly.

[2022-11-09 Tim updates wording following LWG review]

During review of this issue LWG noticed that neither the constructor nor the new overload should accept `subrange`.

The `remove_cv_t` in the new paragraph is added for consistency with LWG 3677.

[Kona 2022-11-12; Set priority to 2]

Proposed resolution:

This wording is relative to N4917 after the application of LWG 3677.

1. Edit 22.3.2 [pairs.pair] as indicated:

   >     template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>& p);
   >     template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>& p);
   >     template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>&& p);
   >     template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>&& p);
   >     template<pair-like P> constexpr explicit(see below) pair(P&& p);

   > > -14- Let `FWD(u)` be `static_cast<decltype(u)>(u)`.

   > > -15- Constraints:

   > > 1. (15.?) — For the last overload, `remove_cvref_t<P>` is not a specialization of `ranges::subrange`,

   > > 2. (15.1) — `is_constructible_v<T1, decltype(get<0>(FWD(p)))>` is `true` and

   > > 3. (15.2) — `is_constructible_v<T2, decltype(get<1>(FWD(p)))>` is `true`.

   > > -16- Effects: Initializes `first` with `get<0>(FWD(p))` and `second` with `get<1>(FWD(p))`.

2. Edit 20.2.2 [memory.syn], header `<memory>` synopsis, as indicated:

   >     namespace std {
   >       […]
   >       // 20.2.8.2 [allocator.uses.construction], uses-allocator construction
   >       […]
   >       template<class T, class Alloc, class U, class V>
   >         constexpr auto uses_allocator_construction_args(const Alloc& alloc,
   >                                                         pair<U, V>& pr) noexcept;

   >       template<class T, class Alloc, class U, class V>
   >         constexpr auto uses_allocator_construction_args(const Alloc& alloc,
   >                                                         const pair<U, V>& pr) noexcept;

   >       template<class T, class Alloc, class U, class V>
   >         constexpr auto uses_allocator_construction_args(const Alloc& alloc,
   >                                                         pair<U, V>&& pr) noexcept;

   >       template<class T, class Alloc, class U, class V>
   >         constexpr auto uses_allocator_construction_args(const Alloc& alloc,
   >                                                         const pair<U, V>&& pr) noexcept;
   >       template<class T, class Alloc, pair-like P>
   >         constexpr auto uses_allocator_construction_args(const Alloc& alloc, P&& p) noexcept;

   >       template<class T, class Alloc, class U>
   >         constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;
   >       […]
   >     }

3. Add the following to 20.2.8.2 [allocator.uses.construction]:

   >       template<class T, class Alloc, pair-like P>
   >         constexpr auto uses_allocator_construction_args(const Alloc& alloc, P&& p) noexcept;

   > > -?- Constraints: `remove_cv_t<T>` is a specialization of `pair` and `remove_cvref_t<P>` is not a specialization of `ranges::subrange`.

   > > -?- Effects: Equivalent to:

   > > >     return uses_allocator_construction_args<T>(alloc, piecewise_construct,
   > > >                                                 forward_as_tuple(get<0>(std::forward<P>(p))),
   > > >                                                 forward_as_tuple(get<1>(std::forward<P>(p))));

4. Edit 20.2.8.2 [allocator.uses.construction] p17:

   >       template<class T, class Alloc, class U>
   >         constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;

   > > -16- Let `FUN` be the function template:

   > > >       template<class A, class B>
   > > >       void FUN(const pair<A, B>&);

   > > -17- Constraints: `remove_cv_t<T>` is a specialization of `pair`, and either:

   > > 1. (17.1) — `remove_cvref_t<P>` is a specialization of `ranges::subrange`, or

   > > 2. (17.2) — `P` does not satisfy `pair-like` and the expression `FUN(u)` is not well-formed when considered as an unevaluated operand..