shared_ptr converting constructorsSection: 20.3.2.2.2 [util.smartptr.shared.const] Status: C++20 Submitter: Casey Carter Opened: 2019-07-10 Last modified: 2021-02-25
Priority: 0
View other active issues in [util.smartptr.shared.const].
View all other issues in [util.smartptr.shared.const].
View all issues with C++20 status.
Discussion:
Issue 2875 added 20.3.2.2.2 [util.smartptr.shared.const] paragraph 13:
Remarks: Whenwhich pertains to the four constructor overloads:Tis an array type, this constructor shall not participate in overload resolution unlessis_move_constructible_v<D>istrue, the expressiond(p)is well-formed, and eitherTisU[N]andY(*)[N]is convertible toT*, orTisU[]andY(*)[]is convertible toT*. WhenTis not an array type, this constructor shall not participate in overload resolution unlessis_move_constructible_v<D>istrue, the expressiond(p)is well-formed, andY*is convertible toT*.
which is fine (ignoring for now that two occurrences of "this constructor" should read "these constructors") for the two overloads with a template parametertemplate<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);
Y, but not so much for the
two with no such template parameter.
MSVC ignores the constraints on Y for the overloads with no such template parameter,
whereas libstdc++ and libc++ seem to ignore all of the constraints for those overloads (See
Compiler Explorer). We should fix the broken wording,
ideally by requiring the MSVC interpretation - the nullptr_t constructors participate in
overload resolution only when is_movable_v<D> is true and d(p) is
well-formed - so concepts and traits that check constructibility are correct.
[2019-11-17 Issue Prioritization]
Status to Tentatively Ready and priority to 0 after six positive votes on the reflector.
Proposed resolution:
This wording is relative to N4835.
Modify 20.3.2.2.2 [util.smartptr.shared.const] as indicated:
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);-?- Constraints:
is_move_constructible_v<D>istrue, andd(p)is a well-formed expression. For the first two overloads:
If
Tis an array type, then eitherTisU[N]andY(*)[N]is convertible toT*, orTisU[]andY(*)[]is convertible toT*.If
Tis not an array type, thenY*is convertible toT*.-9-
RequiresExpects: Construction ofdand a deleter of type […][…]
-13- Remarks: WhenTis an array type, this constructor shall not participate in overload resolution unlessis_move_constructible_v<D>istrue, the expressiond(p)is well-formed, and eitherTisU[N]andY(*)[N]is convertible toT*, orTisU[]andY(*)[]is convertible toT*. WhenTis not an array type, this constructor shall not participate in overload resolution unlessis_move_constructible_v<D>istrue, the expressiond(p)is well-formed, andY*is convertible toT*.