std::shared_ptr
Section: 20.3.2.2.2 [util.smartptr.shared.const] Status: New Submitter: Jiang An Opened: 2023-12-25 Last modified: 2024-03-15
Priority: 4
View other active issues in [util.smartptr.shared.const].
View all other issues in [util.smartptr.shared.const].
View all issues with New status.
Discussion:
Currently, 20.3.2.2.2 [util.smartptr.shared.const]/3 and /9.1 says Y(*)[N]
and Y(*)[]
,
however, they may be invalid types when Y
is an array type of unknown bound or a function type.
Presumably, the constraints should be satisfied only when the mentioned Y(*)[N]
or Y(*)[]
is valid.
[2024-03-15; Reflector poll]
Set priority to 4 after reflector poll.
Jens pointed out that "convertible", as a core language concept, goes from "expression" to "type", not from "type" to "type".
Previous resolution [SUPERSEDED]:
This wording is relative to N4971.
Modify 20.3.2.2.2 [util.smartptr.shared.const] as indicated:
template<class Y> explicit shared_ptr(Y* p);-3- Constraints: When
[…]T
is an array type, the expressiondelete[] p
is well-formed and eitherT
isU[N]
andY(*)[N]
is a valid type and convertible toT*
, orT
isU[]
andY(*)[]
is a valid type and convertible toT*
. WhenT
is not an array type, the expressiondelete p
is well-formed andY*
is convertible toT*
.template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template<class D> shared_ptr(nullptr_t p, D d); template<class D, class A> shared_ptr(nullptr_t p, D d, A a);-9- Constraints:
is_move_constructible_v<D>
istrue
, andd(p)
is a well-formed expression. For the first two overloads:
(9.1) — If
T
is an array type, then eitherT
isU[N]
andY(*)[N]
is a valid type and convertible toT*
, orT
isU[]
andY(*)[]
is a valid type and convertible toT*
.(9.2) — If
T
is not an array type, thenY*
is convertible toT*
.[…]
[2024-03-15; Jonathan provides alternative wording]
Can we just use is_convertible_v<Y(*)[N], T*>
?
With enable_if
-style SFINAE an invalid type will cause substitution failure
and with a requires-clause the constraints won't be satisfied.
Either way we get the desired outcome.
Also, the delete expression is already required to be well-formed, which
rules out function types, so that part of the issue is NAD.
Proposed resolution:
This wording is relative to N4971.
Modify 20.3.2.2.2 [util.smartptr.shared.const] as indicated:
template<class Y> explicit shared_ptr(Y* p);-3- Constraints: When
T
is an array type, the expressiondelete[] p
is well-formed and either:T
isU[N]
andY(*)[N]
is convertible toT*
, orT
isU[]
andY(*)[]
is convertible toT*
.
- —
is_bounded_array_v<T> && is_convertible_v<Y(*)[rank_v<T>], T*>
istrue
, or- —
is_unbounded_array_v<T> && is_convertible_v<Y(*)[], T*>
istrue
.When
T
is not an array type, the expressiondelete p
is well-formed andY*
is convertible toT*
is_convertible_v<Y*, T*>
istrue
.[…]
template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template<class D> shared_ptr(nullptr_t p, D d); template<class D, class A> shared_ptr(nullptr_t p, D d, A a);-9- Constraints:
is_move_constructible_v<D>
istrue
, andd(p)
is a well-formed expression. For the first two overloads:
(9.1) — If
T
is an array type, then either:T
isU[N]
andY(*)[N]
is convertible toT*
, orT
isU[]
andY(*)[]
is convertible toT*
.
- —
is_bounded_array_v<T> && is_convertible_v<Y(*)[rank_v<T>], T*>
istrue
, or- —
is_unbounded_array_v<T> && is_convertible_v<Y(*)[], T*>
istrue
.(9.2) — If
T
is not an array type, thenY*
is convertible toT*
is_convertible_v<Y*, T*>
istrue
.[…]