Title
is_constructible_v<unique_ptr<P, D>, P, D const &> should be false when D is not copy constructible
Status
c++17
Section
[unique.ptr.single.ctor]
Submitter
United States

Created on 2017-02-03.00:00:00 last changed 90 months ago

Messages

Date: 2017-03-03.22:08:49

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:

  • If D is not an lvalue reference type then
    • If d is an lvalue or const rvalue then the first constructor of this pair will be selected. D shall satisfy the requirements of CopyConstructible (Table 24), and the copy constructor of D shall not throw an exception. This unique_ptr will hold a copy of d.
    • Otherwise, d is a non-const rvalue and the second constructor of this pair will be selected. D shall satisfy the requirements of MoveConstructible (Table 23), and the move constructor of D shall not throw an exception. This unique_ptr will hold a value move constructed from d.
  • Otherwise D is an lvalue reference type. d shall be reference-compatible with one of the constructors. If d is an rvalue, it will bind to the second constructor of this pair and the program is ill-formed. [Note: The diagnostic could be implemented using a static_assert which assures that D is not a reference type. — end note] Else d is an lvalue and will bind to the first constructor of this pair. The type which D references need not be CopyConstructible nor MoveConstructible. This unique_ptr will hold a D which refers to the lvalue d. [Note: D may not be an rvalue reference type. — end note]

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.

Date: 2017-03-03.22:08:49

[ Kona 2017-02-27 ]

Accepted as Immediate to resolve NB comment.

Date: 2017-02-15.00:00:00

[ 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.

Date: 2017-02-03.00:00:00
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.

History
Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2017-03-05 23:46:08adminsetstatus: immediate -> wp
2017-03-03 22:08:49adminsetmessages: + msg9061
2017-03-03 22:08:49adminsetstatus: new -> immediate
2017-03-01 04:02:40adminsetmessages: + msg9019
2017-03-01 04:02:40adminsetmessages: + msg9018
2017-02-03 00:00:00admincreate