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

Created on 2019-07-10.00:00:00, last changed 2019-07-10.23:53:23.

Messages

Date: 2019-07-10.23:53:23

Proposed resolution:

This wording is relative to N4820.

  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-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
2019-07-10 23:53:23adminsetmessages: + msg10479
2019-07-10 00:00:00admincreate