2875. shared_ptr::shared_ptr(Y*, D, […]) constructors should be constrained

Section: 20.3.2.2.2 [util.smartptr.shared.const] Status: C++17 Submitter: United States Opened: 2017-02-03 Last modified: 2020-09-06

Priority: Not Prioritized

View other active issues in [util.smartptr.shared.const].

View all other issues in [util.smartptr.shared.const].

View all issues with C++17 status.

Discussion:

Addresses US 126

Paragraph 8: This constructor should not participate in overload resolution unless the Requires clause is satisfied. Note that this would therefore apply to some assignment operator and reset overloads, via Effects: equivalent to some code wording.

Proposed change:

Add a Remarks: clause to constrain this constructor not to participate in overload resolution unless the Requires clause is satisfied.

[2017-02 pre-Kona]

See US 125: LWG 2874.

[2017-02-23, Jonathan provides wording]

This wording is relative to N4640.

  1. Modify 20.3.2.2.2 [util.smartptr.shared.const] as indicated:

    1. If the proposed resolution of LWG 2802 has been accepted modify p8 as shown:

      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);
      

      -8- Requires: D shall be MoveConstructible and cConstruction of d and a deleter of type D initialized with std::move(d) shall not throw exceptions. The expression d(p) shall be well formed, shall have well-defined behavior, and shall not throw exceptions. A shall be an allocator (17.5.3.5). When T is U[N], Y(*)[N] shall be convertible to T*; when T is U[], Y(*)[] shall be convertible to T*; otherwise, Y* shall be convertible to T*.

    2. If the proposed resolution of LWG 2802 has not been accepted modify p8 as shown:

      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);
      

      -8- Requires: D shall be CopyConstructible and such cConstruction of d and a copy of d shall not throw exceptions. The destructor of D shall not throw exceptions. The expression d(p) shall be well formed, shall have well defined behavior, and shall not throw exceptions. A shall be an allocator (17.5.3.5). The copy constructor and destructor of A shall not throw exceptions. When T is U[N], Y(*)[N] shall be convertible to T*; when T is U[], Y(*)[] shall be convertible to T*; otherwise, Y* shall be convertible to T*.

  1. In either case, add a Remarks paragraph after p11:

    [Drafting note: If LWG 2802 is not accepted, replace is_move_constructible_v with is_copy_constructible_v.]

    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);
    

    -8- Requires: […]

    […]

    -11- Throws: […]

    -?- 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 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*.

[Kona 2017-02-27: Jonathan updates wording after LWG review]

[Kona 2017-02-27]

Accepted as Immediate to resolve NB comment.

Proposed resolution:

This wording is relative to N4640 as modified by the proposed resolution of LWG 2802.

  1. 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);
    

    -8- Requires: D shall be MoveConstructible and cConstruction of d and a deleter of type D initialized with std::move(d) shall not throw exceptions. The expression d(p) shall be well formed, shall have well-defined behavior, and shall not throw exceptions. A shall be an allocator (17.5.3.5). When T is U[N], Y(*)[N] shall be convertible to T*; when T is U[], Y(*)[] shall be convertible to T*; otherwise, Y* shall be convertible to T*.

  2. Add a Remarks paragraph after p11:

    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);
    

    -8- Requires: […]

    […]

    -11- Throws: […]

    -?- 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*.