const
typesSection: 20.2.8.2 [allocator.uses.construction] Status: New Submitter: Jonathan Wakely Opened: 2019-02-28 Last modified: 2020-05-01
Priority: 3
View all other issues in [allocator.uses.construction].
View all issues with New status.
Discussion:
The new functions added by P0591R4 misbehave for cv-qualified types.
A specialization std::uses_allocator<X, Alloc>
will not match const X
, so
std::uses_allocator_construction_args<const X>
will return a different result from
std::uses_allocator_construction_args<X>
. It makes no sense to construct X
and const X
differently, either the type wants to use an allocator or it doesn't. I think
std::uses_allocator_construction_args<T>
should remove cv-qualifiers before checking
uses_allocator
, so that it works consistently.
std::make_obj_using_allocator
to also strip cv-qualifiers, but it's not
necessary as C++17 guaranteed elision works even for prvalues of const
types. We only need to make the
construction args ignore cv-qualifiers. We don't want to make cv-qualified types ill-formed, because
that would require users of uses-allocator construction to strip cv-qualifiers before using these functions,
e.g. in cases like std::tuple<const int> t(allocator_arg, alloc, 1);
[2019-03-15 Priority set to 3 after reflector discussion]
Previous resolution [SUPERSEDED]:This wording is relative to N4800.
Change 20.2.8.2 [allocator.uses.construction] as indicated:
template <class T, class Alloc, class... Args> auto uses_allocator_construction_args(const Alloc& alloc, Args&&... args) -> see below;[…]-4- Constraints:
-5- Returns: AT
is not a specialization ofpair
.tuple
value determined as follows, whereU
denotes the typeremove_cv_t<T>
:
(5.1) — If
uses_allocator_v<
isTU, Alloc>false
andis_constructible_v<T, Args...>
istrue
, returnforward_as_tuple(std::forward<Args>(args)...)
.(5.2) — Otherwise, if
uses_allocator_v<
isTU, Alloc>true
andis_constructible_v<T, allocator_arg_t, Alloc, Args...>
istrue
, returntuple<allocator_arg_t, const Alloc&, Args&&...>( allocator_arg, alloc, std::forward<Args>(args)...)(5.3) — Otherwise, if
uses_allocator_v<
isTU, Alloc>true
andis_constructible_v<T, Args..., Alloc>
istrue
, returnforward_as_tuple(std::forward<Args>(args)..., alloc)
.(5.4) — Otherwise, the program is ill-formed.
template <class T, class Alloc, class Tuple1, class Tuple2> auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, Tuple1&& x, Tuple2&& y) -> see below;-6- Constraints:
-7- Effects: ForT
is a specialization ofpair
.T
specified as (possiblyconst
)pair<T1, T2>
, equivalent to: […]template <class T, class Alloc, class... Args> T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args);-17- Effects: Equivalent to:
return ::new(static_cast<void*>voidify(*p)) T(make_obj_using_allocator<T>(alloc, std::forward<Args>(args)...));
[2020-05-01; Daniel syncs wording with recent working draft]
The previously needed change for uninitialized_construct_using_allocator
is no longer
required, because the reworded call to construct_at
does do the right thing now.
Proposed resolution:
This wording is relative to N4861.
Change 20.2.8.2 [allocator.uses.construction] as indicated:
template <class T, class Alloc, class... Args> constexpr auto uses_allocator_construction_args(const Alloc& alloc, Args&&... args) noexcept -> see below;[…]-4- Constraints:
-5- Returns: AT
is not a specialization ofpair
.tuple
value determined as follows, whereU
denotes the typeremove_cv_t<T>
:
(5.1) — If
uses_allocator_v<
isTU, Alloc>false
andis_constructible_v<T, Args...>
istrue
, returnforward_as_tuple(std::forward<Args>(args)...)
.(5.2) — Otherwise, if
uses_allocator_v<
isTU, Alloc>true
andis_constructible_v<T, allocator_arg_t, const Alloc&, Args...>
istrue
, returntuple<allocator_arg_t, const Alloc&, Args&&...>( allocator_arg, alloc, std::forward<Args>(args)...)(5.3) — Otherwise, if
uses_allocator_v<
isTU, Alloc>true
andis_constructible_v<T, Args..., const Alloc&>
istrue
, returnforward_as_tuple(std::forward<Args>(args)..., alloc)
.(5.4) — Otherwise, the program is ill-formed.
template <class T, class Alloc, class Tuple1, class Tuple2> constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, Tuple1&& x, Tuple2&& y) noexcept -> see below;-6- Constraints:
-7- Effects: ForT
is a specialization ofpair
.T
specified as (possiblyconst
)pair<T1, T2>
, equivalent to: […]