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

### 2203. `scoped_allocator_adaptor` uses wrong argument types for piecewise construction

Section: 20.5.4 [allocator.adaptor.members] Status: C++14 Submitter: Jonathan Wakely Opened: 2012-10-19 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [allocator.adaptor.members].

View all issues with C++14 status.

Discussion:

In 20.5.4 [allocator.adaptor.members] paragraph 11 the effects clause says a tuple should be constructed with `inner_allocator_type()`, but that creates an rvalue which cannot bind to `inner_allocator_type&`, and would also be wrong if `this->inner_allocator() != inner_allocator_type()`. This could be considered editorial, since the current wording doesn't even compile.

Secondly, in the same paragraph, the tuple objects `xprime` and `yprime` seem to be lvalues and might be constructed by copying `x` and `y`. This prevents using `scoped_allocator` to construct pairs from arguments of move-only types. I believe the `tuple_cast()` expressions should use `std::move(x)` and `std::move(y)` to move from the incoming arguments (which are passed by value to candidates for moving) and the final sentence of the paragraph should be:

then calls `OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST (*this), p, piecewise_construct, std::move(xprime), std::move(yprime))`.

so that the objects are passed to `std::pair`'s piecewise constructor as rvalues and are eligible for moving into the constructor arguments. This could also be considered editorial, as the current wording prevents certain uses which were intended to be supported.

I've implemented these changes and can confirm they allow code to work that can't be compiled according to the current wording.

[2013-03-15 Issues Teleconference]

Moved to Review.

The resolution looks good, with wording provided by a recent implementer. However, it will take more time than the telecon allows to review with confidence, and we would like Pablo to at least take a look over the resolution and confirm that it matches the design intent.

[2013-04-18, Bristol]

Proposed resolution:

This wording is relative to N3376.

1. Change 20.5.4 [allocator.adaptor.members] paragraph 11 as indicated:

   > -11- Effects: Constructs a `tuple` object `xprime` from `x` by the following rules:

   > - If `uses_allocator<T1, inner_allocator_type>::value` is `false` and `is_constructible<T1, Args1...>::value` is `true`, then `xprime` is `x`.

   > - Otherwise, if `uses_allocator<T1, inner_allocator_type>::value` is `true` and `is_constructible<T1, allocator_arg_t, inner_allocator_type, Args1...>::value` is `true`, then `xprime` is `tuple_cat(tuple<allocator_arg_t, inner_allocator_type&>( allocator_arg, inner_allocator_type()), std::move(x))`.

   > - Otherwise, if `uses_allocator<T1, inner_allocator_type>::value` is `true` and `is_constructible<T1, Args1..., inner_allocator_type>::value` is `true`, then `xprime` is `tuple_cat(std::move(x), tuple<inner_allocator_type&>(inner_allocator_type()))`.

   > - Otherwise, the program is ill-formed.

   > and constructs a `tuple` object `yprime` from `y` by the following rules:

   > - If `uses_allocator<T2, inner_allocator_type>::value` is `false` and `is_constructible<T2, Args2...>::value` is `true`, then `yprime` is `y`.

   > - Otherwise, if `uses_allocator<T2, inner_allocator_type>::value` is `true` and `is_constructible<T2, allocator_arg_t, inner_allocator_type, Args2...>::value` is `true`, then `yprime` is `tuple_cat(tuple<allocator_arg_t, inner_allocator_type&>( allocator_arg, inner_allocator_type()), std::move(y))`.

   > - Otherwise, if `uses_allocator<T2, inner_allocator_type>::value` is `true` and `is_constructible<T2, Args2..., inner_allocator_type>::value` is `true`, then `yprime` is `tuple_cat(std::move(y), tuple<inner_allocator_type&>(inner_allocator_type()))`.

   > - Otherwise, the program is ill-formed.

   > then calls `OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, piecewise_construct, std::move(xprime), std::move(yprime))`.