Proposed resolution:
This wording is relative to N4750.
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:: […]
(10.1) — […]
(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)).(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)).(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:
(10.5) — […]
(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)).(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)).(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.