Created on 2021-02-23.00:00:00 last changed 12 months ago
Proposed resolution:
This wording is relative to N4901.
Edit [memory.syn], header <memory> synopsis, as indicated:
namespace std {
[…]
// [allocator.uses.construction], uses-allocator construction
[…]
template<class T, class Alloc, class U, class V>
constexpr auto uses_allocator_construction_args(const Alloc& alloc,
pair<U, V>& pr) noexcept;
template<class T, class Alloc, class U, class V>
constexpr auto uses_allocator_construction_args(const Alloc& alloc,
const pair<U, V>& pr) noexcept;
template<class T, class Alloc, class U, class V>
constexpr auto uses_allocator_construction_args(const Alloc& alloc,
pair<U, V>&& pr) noexcept;
template<class T, class Alloc, class U, class V>
constexpr auto uses_allocator_construction_args(const Alloc& alloc,
const pair<U, V>&& pr) noexcept;
template<class T, class Alloc, class U>
constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;
[…]
}
Add the following to [allocator.uses.construction]:
template<class T, class Alloc, class U> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;-?- Let FUN be the function template:
template<class A, class B> void FUN(const pair<A, B>&);-?- Constraints: T is a specialization of pair, and the expression FUN(u) is not well-formed when considered as an unevaluated operand.
-?- Let pair-constructor be an exposition-only class defined as follows:class pair-constructor { using pair-type = remove_cv_t<T>; // exposition only constexpr auto do-construct(const pair-type& p) const { // exposition only return make_obj_using_allocator<pair-type>(alloc_, p); } constexpr auto do-construct(pair-type&& p) const { // exposition only return make_obj_using_allocator<pair-type>(alloc_, std::move(p)); } const Alloc& alloc_; // exposition only U& u_; // exposition only public: constexpr operator pair-type() const { return do-construct(std::forward<U>(u_)); } };-?- Returns: make_tuple(pc), where pc is a pair-constructor object whose alloc_ member is initialized with alloc and whose u_ member is initialized with u.
[ 2022-02-10 Approved at February 2022 virtual plenary. Status changed: Tentatively Ready → WP. ]
[ 2022-01-31; Reflector poll ]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
[ 2021-12-02 Tim updates PR to avoid public exposition-only members ]
[ 2021-03-12; Reflector poll ]
Set priority to 3 following reflector poll.
Previous resolution [SUPERSEDED]:
This wording is relative to N4878.
Edit [memory.syn], header <memory> synopsis, as indicated:
namespace std { […] // [allocator.uses.construction], uses-allocator construction […] template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair<U, V>& pr) noexcept -> see below; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>&& pr) noexcept -> see below; template<class T, class Alloc, class U> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept; […] }
Add the following to [allocator.uses.construction]:
template<class T, class Alloc, class U> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;-?- Let FUN be the function template:
template<class A, class B> void FUN(const pair<A, B>&);-?- Constraints: T is a specialization of pair, and the expression FUN(u) is not well-formed when considered as an unevaluated operand.
-?- Effects: Equivalent to:return make_tuple(pair-constructor{alloc, u});where pair-constructor is an exposition-only class defined as follows:
struct pair-constructor { using pair-type = remove_cv_t<T>; // exposition only constexpr operator pair-type() const { return do-construct(std::forward<U>(u)); } constexpr auto do-construct(const pair-type& p) const { // exposition only return make_obj_using_allocator<pair-type>(alloc, p); } constexpr auto do-construct(pair-type&& p) const { // exposition only return make_obj_using_allocator<pair-type>(alloc, std::move(p)); } const Alloc& alloc; // exposition only U& u; // exposition only };
[ 2021-02-27 Tim adds PR and comments ]
The superseded resolution below attempts to solve this issue by adding two additional overloads of uses_allocator_construction_args to handle this case. However, the new overloads forces implicit conversions at the call to uses_allocator_construction_args, which requires the result to be consumed within the same full-expression before any temporary created from the conversion is destroyed. This is not the case for the piecewise_construct overload of uses_allocator_construction_args, which recursively calls uses_allocator_construction_args for the two elements of the pair, which might themselves be pairs.
The approach taken in the revised PR is to produce an exposition-only pair-constructor object instead. The object holds the allocator and the argument by reference, implicitly converts to the specified specialization of pair, and when so converted return a pair that is constructed by uses-allocator construction with the converted value of the original argument. This maintains the existing design that pair itself doesn't know anything about allocator construction.
Previous resolution [SUPERSEDED]:
This wording is relative to N4878.
Edit [memory.syn], header <memory> synopsis, as indicated:
namespace std { […] // [allocator.uses.construction], uses-allocator construction […] template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const remove_cv_t<T>& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair<U, V>& pr) noexcept -> see below; template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc, remove_cv_t<T>&& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>&& pr) noexcept -> see below; […] }
Edit [allocator.uses.construction] as indicated:
template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const remove_cv_t<T>& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair<U, V>& pr) noexcept -> see below;-12- Constraints: T is a specialization of pair. For the second overload, is_same_v<pair<U, V>, remove_cv_t<T>> is false.
-13- Effects: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(pr.first), forward_as_tuple(pr.second));template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc, remove_cv_t<T>&& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>&& pr) noexcept -> see below;-14- Constraints: T is a specialization of pair. For the second overload, is_same_v<pair<U, V>, remove_cv_t<T>> is false.
-15- Effects: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(std::move(pr).first), forward_as_tuple(std::move(pr).second));
As currently specified, the following program is ill-formed (and appears to have been since LWG 2975):
struct S { operator std::pair<const int, int>() const { return {}; } }; void f() { std::pmr::map<int, int> s; s.emplace(S{}); }
There's no matching overload for uses_allocator_construction_args<pair<const int, int>>(alloc, S&&), since S is not a pair and every overload for constructing pairs that takes one non-allocator argument expects a pair from which template arguments can be deduced.
History | |||
---|---|---|---|
Date | User | Action | Args |
2023-11-22 15:47:43 | admin | set | status: wp -> c++23 |
2022-02-10 12:58:57 | admin | set | messages: + msg12347 |
2022-02-10 12:58:57 | admin | set | status: ready -> wp |
2022-01-31 09:53:14 | admin | set | messages: + msg12335 |
2022-01-31 09:53:14 | admin | set | status: new -> ready |
2021-12-03 00:51:29 | admin | set | messages: + msg12238 |
2021-03-12 15:07:58 | admin | set | messages: + msg11729 |
2021-02-27 21:31:13 | admin | set | messages: + msg11715 |
2021-02-27 21:31:13 | admin | set | messages: + msg11714 |
2021-02-23 00:00:00 | admin | create |