2905. is_constructible_v<unique_ptr<P, D>, P, D const &> should be false when D is not copy constructible

Section: 20.3.1.3.2 [unique.ptr.single.ctor] Status: C++17 Submitter: United States Opened: 2017-02-03 Last modified: 2017-07-30

Priority: Not Prioritized

View all other issues in [unique.ptr.single.ctor].

View all issues with C++17 status.

Discussion:

Addresses US 123

is_constructible_v<unique_ptr<P, D>, P, D const &> should be false when D is not copy constructible, and similarly for D&& when D is not move constructible. This could be achieved by the traditional 'does not participate in overload resolution' wording, or similar.

Proposed change: Add a Remarks: clause to constrain the appropriate constructors.

[2017-02-28, Jonathan comments and provides concrete wording]

As well as addressing the NB comment, this attempts to make some further improvements to the current wording, which is a little strange. It incorrectly uses "d" to mean the constructor argument that initializes the parameter d, and unnecessarily explains how overload resolution works for lvalues and rvalues. It refers to the copy/move constructor of D, but the constructor that is selected to perform the initialization may not be a copy/move constructor (e.g. initializing a deleter object from an rvalue might use a copy constructor if there is no move constructor). The condition "d shall be reference compatible with one of the constructors" is bogus: reference compatible is a property of two types, not a value and a constructor, and again is trying to talk about the argument not the parameter.

Note that we could replace the "see below" in the signatures and paragraphs 9, 10 and 11 by declaring the constructors as:

unique_ptr(pointer p, const D& d) noexcept;
unique_ptr(pointer p, remove_reference_t<D>&& d) noexcept;

I think this produces the same signatures in all cases. I haven't proposed that here, it could be changed separately if desired.

[Kona 2017-02-27]

Accepted as Immediate to resolve NB comment.

Proposed resolution:

Modify [unique.ptr.single.ctor] paragraphs 9-11 as shown:

unique_ptr(pointer p, see below d1) noexcept;
unique_ptr(pointer p, see below d2) noexcept;

-9- The signature of these constructors depends upon whether D is a reference type. If D is a non-reference type A, then the signatures are

  unique_ptr(pointer p, const A& d) noexcept;
  unique_ptr(pointer p, A&& d) noexcept;

-10- If D is an lvalue reference type A&, then the signatures are:

  unique_ptr(pointer p, A& d) noexcept;
  unique_ptr(pointer p, A&& d) = delete;

-11- If D is an lvalue reference type const A&, then the signatures are:

  unique_ptr(pointer p, const A& d) noexcept;
  unique_ptr(pointer p, const A&& d) = delete;

Remove paragraph 12 entirely:

-12- Requires:

Modify paragraph 13 as shown:

-13- Effects: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and initializing the deleter as described above from std::forward<decltype(d)>(d).

Add a new paragraph after paragraph 14 (Postconditions):

-?- Remarks: These constructors shall not participate in overload resolution unless is_constructible_v<D, decltype(d)> is true.