Created on 2019-02-28.00:00:00 last changed 55 months ago
Proposed resolution:
This wording is relative to N4861.
Change [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: T is not a specialization of pair.
-5- Returns: A tuple value determined as follows, where U denotes the type remove_cv_t<T>:
(5.1) — If uses_allocator_v<
TU, Alloc> is false and is_constructible_v<T, Args...> is true, return forward_as_tuple(std::forward<Args>(args)...).(5.2) — Otherwise, if uses_allocator_v<
TU, Alloc> is true and is_constructible_v<T, allocator_arg_t, const Alloc&, Args...> is true, returntuple<allocator_arg_t, const Alloc&, Args&&...>( allocator_arg, alloc, std::forward<Args>(args)...)(5.3) — Otherwise, if uses_allocator_v<
TU, Alloc> is true and is_constructible_v<T, Args..., const Alloc&> is true, return forward_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: T is a specialization of pair.
-7- Effects: For T specified as (possibly const) pair<T1, T2>, equivalent to: […]
[ 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.
[ 2019-03-15 Priority set to 3 after reflector discussion ]
Previous resolution [SUPERSEDED]:This wording is relative to N4800.
Change [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: T is not a specialization of pair.
-5- Returns: A tuple value determined as follows, where U denotes the type remove_cv_t<T>:
(5.1) — If uses_allocator_v<
TU, Alloc> is false and is_constructible_v<T, Args...> is true, return forward_as_tuple(std::forward<Args>(args)...).(5.2) — Otherwise, if uses_allocator_v<
TU, Alloc> is true and is_constructible_v<T, allocator_arg_t, Alloc, Args...> is true, returntuple<allocator_arg_t, const Alloc&, Args&&...>( allocator_arg, alloc, std::forward<Args>(args)...)(5.3) — Otherwise, if uses_allocator_v<
TU, Alloc> is true and is_constructible_v<T, Args..., Alloc> is true, return forward_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: T is a specialization of pair.
-7- Effects: For T specified as (possibly const) 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)...));
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.
We could consider changing 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);History | |||
---|---|---|---|
Date | User | Action | Args |
2020-05-01 20:07:01 | admin | set | messages: + msg11254 |
2019-03-16 08:03:53 | admin | set | messages: + msg10353 |
2019-03-03 22:12:53 | admin | set | messages: + msg10338 |
2019-02-28 00:00:00 | admin | create |