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.

### 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:

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