This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++17 status.

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

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

Priority: Not Prioritized

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.11.3.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 c Construction 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 c Construction 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.11.3.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 c Construction 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*`.