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.
scoped_allocator_adaptor
uses wrong argument types for piecewise constructionSection: 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.
[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.
Change 20.5.4 [allocator.adaptor.members] paragraph 11 as indicated:
-11- Effects: Constructs a
tuple
objectxprime
fromx
by the following rules:
If
uses_allocator<T1, inner_allocator_type>::value
isfalse
andis_constructible<T1, Args1...>::value
istrue
, thenxprime
isx
.Otherwise, if
uses_allocator<T1, inner_allocator_type>::value
istrue
andis_constructible<T1, allocator_arg_t, inner_allocator_type, Args1...>::value
istrue
, thenxprime
istuple_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
istrue
andis_constructible<T1, Args1..., inner_allocator_type>::value
istrue
, thenxprime
istuple_cat(std::move(x), tuple<inner_allocator_type&>(inner_allocator
._type()))Otherwise, the program is ill-formed.
and constructs a
tuple
objectyprime
fromy
by the following rules:
If
uses_allocator<T2, inner_allocator_type>::value
isfalse
andis_constructible<T2, Args2...>::value
istrue
, thenyprime
isy
.Otherwise, if
uses_allocator<T2, inner_allocator_type>::value
istrue
andis_constructible<T2, allocator_arg_t, inner_allocator_type, Args2...>::value
istrue
, thenyprime
istuple_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
istrue
andis_constructible<T2, Args2..., inner_allocator_type>::value
istrue
, thenyprime
istuple_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))
.