This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.
make_shared
(sub)object destruction semantics are not specifiedSection: 20.3.2.2.7 [util.smartptr.shared.create] Status: C++20 Submitter: Glen Joseph Fernandes Opened: 2017-08-06 Last modified: 2021-02-25
Priority: 2
View all other issues in [util.smartptr.shared.create].
View all issues with C++20 status.
Discussion:
The remarks for the make_shared
and allocate_shared
functions
do not specify how the objects managed by the returned shared_ptr
are
destroyed. It is implied that when objects are constructed via a placement new
expression, they are destroyed by calling the destructor, and that when objects
are constructed via an allocator, they are destroyed using that allocator. This
should be explicitly specified.
[2017-11 Albuquerque Wednesday night issues processing]
Priority set to 2
Previous resolution [SUPERSEDED]:
This resolution is relative to N4687.
Edit 20.3.2.2.7 [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);[…]
-7- Remarks:
[…]
(7.9) — When the lifetime of the object managed by the return value ends, or when the initialization of an array element throws an exception, the initialized elements should be destroyed in the reverse order of their construction.
(7.?) — When a (sub)object of a non-array type
U
that was initialized bymake_shared
is to be destroyed, it shall be destroyed via the expressionpv->~U()
wherepv
points to that object of typeU
.(7.?) — When a (sub)object of a non-array type
U
that was initialized byallocate_shared
is to be destroyed, it shall be destroyed via the expressionallocator_traits<A2>::destroy(a2, pv)
wherepv
points to that object of type cv-unqualifiedU
anda2
of typeA2
is a rebound copy of the allocatora
passed toallocate_shared
such that itsvalue_type
isremove_cv_t<U>
.
[2018-06 Rapperswil Wednesday night issues processing]
CC: what is "of type cv-unqualified U
" and "remove_cv_T<U>
" about?
DK: again, it isn't new wording; it is in p 7.5.2
JW: but none of the words use "of type cv-unqualified U
"
CT: so we should also used remove_cv_T<U>
instead?
JW: I would like to talk to Glen
FB: does anybody know how it works for an array of arrays? It seems to cover the case
JW: we could leave it vague as it is now or specify it to exactly what it does
DK: I think we should split the thing into two parts and start with definitions
DK: ACTION I can refactor the wording
MC: there was a fairly long message thread when we talked about this
C
and pointer variable c
as well as
Table 31 expressions "a.construct(c, args)
" and "a.destroy(c)
"), therefore a
conforming implementation needs to effectively construct an object pointer that holds an object of type
remove_cv_T<U>
and similarly destroy such an object. Albeit it seems to be an artificial
restriction to construct and destroy only non-cv-qualified object types, this is, if any,
a different issue. But given this current state, the wording for allocate_shared
needs
to make a special wording dance via remove_cv_T<U>
.
For construct
the existing wording prevents to speak about that detail by using the more indirect
phrase "where pv
points to storage suitable to hold an object of type U
", but since
object types U
and const U
have exactly the same storage and alignment requirements,
this sentence is correct for remove_cv_T<U>
as well.
[2018-08-23 Batavia Issues processing]
Status to Tentatively Ready.
[2018-11, Adopted in San Diego]
Proposed resolution:
This resolution is relative to N4750.
Edit 20.3.2.2.7 [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);[…]
-7- Remarks:
[…]
(7.9) — When the lifetime of the object managed by the return value ends, or when the initialization of an array element throws an exception, the initialized elements are destroyed in the reverse order of their original construction.
(7.?) — When a (sub)object of a non-array type
U
that was initialized bymake_shared
is to be destroyed, it is destroyed via the expressionpv->~U()
wherepv
points to that object of typeU
.(7.?) — When a (sub)object of a non-array type
U
that was initialized byallocate_shared
is to be destroyed, it is destroyed via the expressionallocator_traits<A2>::destroy(a2, pv)
wherepv
points to that object of typeremove_cv_t<U>
anda2
of typeA2
is a rebound copy of the allocatora
passed toallocate_shared
such that itsvalue_type
isremove_cv_t<U>
.