Title
Broken requirements for shared_ptr converting constructors
Status
c++20
Section
[util.smartptr.shared.const]
Submitter
Casey Carter

Created on 2019-07-10.00:00:00 last changed 46 months ago

Messages

Date: 2019-11-17.12:16:59

Proposed resolution:

This wording is relative to N4835.

  1. Modify [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> is true, and d(p) is a well-formed expression. For the first two overloads:

    • If T is an array type, then either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*.

    • If T is not an array type, then Y* is convertible to T*.

    -9- RequiresExpects: Construction of d and a deleter of type […]

    […]

    -13- Remarks: When T is an array type, this constructor shall not participate in overload resolution unless is_move_constructible_v<D> is true, the expression d(p) is well-formed, and either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*. When T is not an array type, this constructor shall not participate in overload resolution unless is_move_constructible_v<D> is true, the expression d(p) is well-formed, and Y* is convertible to T*.

Date: 2019-11-17.00:00:00

[ 2019-11-17 Issue Prioritization ]

Status to Tentatively Ready and priority to 0 after six positive votes on the reflector.

Date: 2019-07-10.00:00:00

Issue 2875 added [util.smartptr.shared.const] paragraph 13:

Remarks: When T is an array type, this constructor shall not participate in overload resolution unless is_move_constructible_v<D> is true, the expression d(p) is well-formed, and either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*. When T is not an array type, this constructor shall not participate in overload resolution unless is_move_constructible_v<D> is true, the expression d(p) is well-formed, and Y* is convertible to T*.
which pertains to the four constructor overloads:
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);
which is fine (ignoring for now that two occurrences of "this constructor" should read "these constructors") for the two overloads with a template parameter 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.

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2020-02-24 16:02:59adminsetstatus: voting -> wp
2020-01-17 04:54:50adminsetstatus: ready -> voting
2019-11-17 12:16:59adminsetmessages: + msg10824
2019-11-17 12:16:59adminsetstatus: new -> ready
2019-07-10 23:53:23adminsetmessages: + msg10479
2019-07-10 00:00:00admincreate