Issue 3216: Rebinding the allocator before calling construct/destroy in allocate_shared (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.
3216. Rebinding the allocator before calling construct/destroy in allocate_shared
Section: 20.3.2.2.7 [util.smartptr.shared.create] Status: WP Submitter: Billy O'Neal III Opened: 2019-06-11 Last modified: 2024-11-28
Priority: 3
View all other issues in [util.smartptr.shared.create].
View all issues with WP status.
Discussion:
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…
[2019-07 Issue Prioritization]
Priority to 3 after discussion on the reflector.
Previous resolution [SUPERSEDED]:
This wording is relative to N4810.
- Modify 20.3.2.2.7 [util.smartptr.shared.create] as indicated:
[_Drafting note:_ The edits to change
pvtopuwere suggested by Jonathan Wakely (thanks!). This wording also has theremove_cv_tfixes specified by LWG 3210(i)— if that change is rejected some of those have to be stripped here.]
template<class T, ...>
shared_ptr make_shared(args);
template<class T, class A, ...>
shared_ptr allocate_shared(const A& a, args);
template<class T, ...>
shared_ptr make_shared_default_init(args);
template<class T, class A, ...>
shared_ptr 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
Uis specified to have an initial value ofv, orU(l...), wherel...is a list of constructor arguments,allocate_sharedshall initialize this (sub)object via the expression
- (7.5.1) —
allocator_traits<A2>::construct(a2, p~~v~~u, v)or2. (7.5.2) — `allocator_traits<A2>::construct(a2, p~~v~~u, l...)`respectively, where
p~~v~~uis a pointer of typeremove_cv_t<U>*pointsing to storage suitable to hold an object of typeremove_cv_t<U>anda2of typeA2is a potentially rebound copy of the allocatorapassed toallocate_sharedsuch that its.value_typeisremove_cv_t<U>
4. (7.6) — […]
5. (7.7) — When a (sub)object of non-array typeUis specified to have a default initial value,allocate_sharedshallinitializes this (sub)object via the expressionallocator_traits<A2>::construct(a2, p~~v~~u), wherep~~v~~uis a pointer of typeremove_cv_t<U>*pointsing to storage suitable to hold an object of typeremove_cv_t<U>anda2of typeA2is apotentially rebound copy of the allocatorapassed toallocate_sharedsuch that its.value_typeisremove_cv_t<U>
6. […]
7. (7.12) — When a (sub)object of non-array typeUthat was initialized byallocate_sharedis to be destroyed, it is destroyed via the expressionallocator_traits<A2>::destroy(a2, p~~v~~u)wherep~~v~~uis a pointer of typeremove_cv_t<U>*pointsing to that object of typeremove_cv_t<U>anda2of typeA2is a potentially rebound copy of the allocatorapassed toallocate_sharedsuch that its.value_typeisremove_cv_t<U>
[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(i).
[2024-10-02; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
[Wrocław 2024-11-23; Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4988.
- Modify 20.3.2.2.7 [util.smartptr.shared.create] as indicated:
template<class T, ...>
shared_ptr make_shared(args);
template<class T, class A, ...>
shared_ptr allocate_shared(const A& a, args);
template<class T, ...>
shared_ptr make_shared_for_overwrite(args);
template<class T, class A, ...>
shared_ptr 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
Uis specified to have an initial value ofv, orU(l...), wherel...is a list of constructor arguments,allocate_sharedshall initialize this (sub)object via the expression- (7.5.1) —
allocator_traits<A2>::construct(a2, p~~v~~u, v)or
- (7.5.1) —
2. (7.5.2) — `allocator_traits<A2>::construct(a2, p~~v~~u, l...)`respectively, where
p~~v~~uis a pointer of typeremove_cv_t<U>*pointsing to storage suitable to hold an object of typeremove_cv_t<U>anda2of typeA2is a potentially rebound copy of the allocatorapassed toallocate_sharedsuch that its.value_typeisremove_cv_t<U>
4. (7.6) — […]
5. (7.7) — When a (sub)object of non-array typeUis specified to have a default initial value,allocate_sharedshallinitializes this (sub)object via the expressionallocator_traits<A2>::construct(a2, p~~v~~u), wherep~~v~~uis a pointer of typeremove_cv_t<U>*pointsing to storage suitable to hold an object of typeremove_cv_t<U>anda2of typeA2is apotentially rebound copy of the allocatorapassed toallocate_sharedsuch that its.value_typeisremove_cv_t<U>
6. […]
7. > [_Drafting note_: Issue 4024(i) will addmake_shared_for_overwriteandallocate_shared_for_overwriteto (7.11) but that doesn't conflict with this next edit.]
(7.11) — When a (sub)object of non-array typeUthat was initialized bymake_sharedis to be destroyed, it is destroyed via the expressionp~~v~~u->~U()wherep~~v~~upoints to that object of typeU.
8. (7.12) — When a (sub)object of non-array typeUthat was initialized byallocate_sharedis to be destroyed, it is destroyed via the expressionallocator_traits<A2>::destroy(a2, p~~v~~u)wherep~~v~~uis a pointer of typeremove_cv_t<U>*pointsing to that object of typeremove_cv_t<U>anda2of typeA2is a potentially rebound copy of the allocatorapassed toallocate_sharedsuch that its.value_typeisremove_cv_t<U>