Created on 2019-06-11.00:00:00 last changed yesterday
Proposed resolution:
This wording is relative to N4988.
Modify [util.smartptr.shared.create] as indicated:
template<class T, ...> shared_ptr<T> make_shared(args); template<class T, class A, ...> shared_ptr<T> allocate_shared(const A& a, args); template<class T, ...> shared_ptr<T> make_shared_for_overwrite(args); template<class T, class A, ...> shared_ptr<T> allocate_shared_for_overwrite(const A& a, args);-2- Preconditions: […]
[…] -7- Remarks:
(7.1) — […]
[…]
(7.5) — When a (sub)object of a non-array type U is specified to have an initial value of v, or U(l...), where l... is a list of constructor arguments, allocate_shared shall initialize this (sub)object via the expression
(7.5.1) — allocator_traits<A2>::construct(a2, p
vu, v) or(7.5.2) — allocator_traits<A2>::construct(a2, p
vu, l...)respectively, where p
vu is a pointer of type remove_cv_t<U>* pointsing to storage suitable to hold an object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_sharedsuch that its value_type is remove_cv_t<U>.(7.6) — […]
(7.7) — When a (sub)object of non-array type U is specified to have a default initial value, allocate_shared
shallinitializes this (sub)object via the expression allocator_traits<A2>::construct(a2, pvu), where pvu is a pointer of type remove_cv_t<U>* pointsing to storage suitable to hold an object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_sharedsuch that its value_type is remove_cv_t<U>.[…]
[Drafting note: Issue 4024 will add `make_shared_for_overwrite` and `allocate_shared_for_overwrite` to (7.11) but that doesn't conflict with this next edit.]
(7.11) — When a (sub)object of non-array type U that was initialized by make_shared is to be destroyed, it is destroyed via the expression
p
wherevu->~U()p
points to that object of typevuU
.(7.12) — When a (sub)object of non-array type U that was initialized by allocate_shared is to be destroyed, it is destroyed via the expression allocator_traits<A2>::destroy(a2, p
vu) where pvu is a pointer of type remove_cv_t<U>* pointsing to that object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_sharedsuch that its value_type is remove_cv_t<U>.
[ 2024-10-02; Reflector poll ]
Set status to Tentatively Ready after six votes in favour during reflector poll.
[ 2024-08-23; Jonathan provides updated wording ]
`make_shared_default_init` and `allocate_shared_default_init` were renamed
by P1973R1 so this needs a rebase.
The edit to (7.11) is just for consistency, so that `pv` is always `void*`
and `pu` is remove_cv_t<U>*
.
Accepting this proposed resolution would also resolve issue 3210.
[ 2019-07 Issue Prioritization ]
Priority to 3 after discussion on the reflector.
This wording is relative to N4810.
Modify [util.smartptr.shared.create] as indicated:
[Drafting note: The edits to change pv to pu were suggested by Jonathan Wakely (thanks!). This wording also has the remove_cv_t fixes specified by LWG 3210 — if that change is rejected some of those have to be stripped here.]
template<class T, ...> shared_ptr<T> make_shared(args); template<class T, class A, ...> shared_ptr<T> allocate_shared(const A& a, args); template<class T, ...> shared_ptr<T> make_shared_default_init(args); template<class T, class A, ...> shared_ptr<T> allocate_shared_default_init(const A& a, args);-2- Requires: […]
[…] -7- Remarks:
(7.1) — […]
[…]
(7.5) — When a (sub)object of a non-array type U is specified to have an initial value of v, or U(l...), where l... is a list of constructor arguments, allocate_shared shall initialize this (sub)object via the expression
(7.5.1) — allocator_traits<A2>::construct(a2, p
vu, v) or(7.5.2) — allocator_traits<A2>::construct(a2, p
vu, l...)respectively, where p
vu is a pointer of type remove_cv_t<U>* pointsing to storage suitable to hold an object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_sharedsuch that its value_type is remove_cv_t<U>.(7.6) — […]
(7.7) — When a (sub)object of non-array type U is specified to have a default initial value, allocate_shared
shallinitializes this (sub)object via the expression allocator_traits<A2>::construct(a2, pvu), where pvu is a pointer of type remove_cv_t<U>* pointsing to storage suitable to hold an object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_sharedsuch that its value_type is remove_cv_t<U>.[…]
(7.12) — When a (sub)object of non-array type U that was initialized by allocate_shared is to be destroyed, it is destroyed via the expression allocator_traits<A2>::destroy(a2, p
vu) where pvu is a pointer of type remove_cv_t<U>* pointsing to that object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_sharedsuch that its value_type is remove_cv_t<U>.
The new allocate_shared wording says we need to rebind the allocator back to T's type before we can call construct or destroy, but this is suboptimal (might make extra unnecessary allocator copies), and is inconsistent with the containers' behavior, which call allocator construct on whatever T they want. (For example, std::list<T, alloc<T>> rebinds to alloc<_ListNode<T>>, but calls construct(T*) without rebinding back)
It seems like we should be consistent with the containers and not require a rebind here. PR would look something like this, relative to N4810; I'm still not super happy with this wording because it looks like it might be saying a copy of the allocator must be made we would like to avoid…History | |||
---|---|---|---|
Date | User | Action | Args |
2024-11-19 16:09:07 | admin | set | status: ready -> voting |
2024-10-02 12:02:45 | admin | set | messages: + msg14401 |
2024-10-02 12:02:45 | admin | set | status: new -> ready |
2024-08-23 10:32:02 | admin | set | messages: + msg14342 |
2019-07-23 15:26:26 | admin | set | messages: + msg10498 |
2019-06-13 19:52:05 | admin | set | messages: + msg10438 |
2019-06-11 00:00:00 | admin | create |