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

### 762. `std::unique_ptr` requires complete type?

Section: 20.3.1 [unique.ptr] Status: CD1 Submitter: Daniel Krügler Opened: 2007-11-30 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [unique.ptr].

View all issues with CD1 status.

Discussion:

In contrast to the proposed `std::shared_ptr`, `std::unique_ptr` does currently not support incomplete types, because it gives no explicit grant - thus instantiating `unique_ptr` with an incomplete pointee type `T` automatically belongs to undefined behaviour according to 16.4.5.8 [res.on.functions]/2, last bullet. This is an unnecessary restriction and prevents many well-established patterns - like the bridge pattern - for `std::unique_ptr`.

[ Bellevue: ]

> Move to open. The LWG is comfortable with the intent of allowing incomplete types and making `unique_ptr` more like `shared_ptr`, but we are not comfortable with the wording. The specification for `unique_ptr` should be more like that of `shared_ptr`. We need to know, for individual member functions, which ones require their types to be complete. The `shared_ptr` specification is careful to say that for each function, and we need the same level of care here. We also aren't comfortable with the "part of the operational semantic" language; it's not used elsewhere in the standard, and it's not clear what it means. We need a volunteer to produce new wording.

Proposed resolution:

The proposed changes in the following revision refers to the current state of N2521 including the assumption that [unique.ptr.compiletime] will be removed according to the current state of 740.

The specialization `unique_ptr<T[]>` has some more restrictive constraints on type-completeness on `T` than `unique_ptr<T>`. The following proposed wordings try to cope with that. If the committee sees less usefulness on relaxed constraints on `unique_ptr<T[]>`, the alternative would be to stop this relaxation e.g. by adding one further bullet to 20.3.1.4 [unique.ptr.runtime]/1: "`T` shall be a complete type, if used as template argument of `unique_ptr<T[], D>`

This issue has some overlap with 673, but it seems not to cause any problems with this one, because 673 adds only optional requirements on `D` that do not conflict with the here discussed ones, provided that `D::pointer`'s operations (including default construction, copy construction/assignment, and pointer conversion) are specified not to throw, otherwise this would have impact on the current specification of `unique_ptr`.

1. In 20.3.1 [unique.ptr]/2 add as the last sentence to the existing para:

   > The `unique_ptr` provides a semantics of strict ownership. A `unique_ptr` owns the object it holds a pointer to. A `unique_ptr` is not `CopyConstructible`, nor `CopyAssignable`, however it is `MoveConstructible` and `MoveAssignable`. The template parameter `T` of `unique_ptr` may be an incomplete type. [ Note: The uses of `unique_ptr` include providing exception safety for dynamically allcoated memory, passing ownership of dynamically allocated memory to a function, and returning dynamically allocated memory from a function. -- end note ]

2. 20.3.1.3.2 [unique.ptr.single.ctor]/1: No changes necessary.

   > [ N.B.: We only need the requirement that `D` is `DefaultConstructible`. The current wording says just this. ]

3. In 20.3.1.3.2 [unique.ptr.single.ctor]/5 change the requires clause to say:

   > Requires: The expression `D()(p)` shall be well formed. The default constructor of `D` shall not throw an exception. `D` must not be a reference type. `D` shall be default constructible, and that construction shall not throw an exception.

   > [ N.B.: There is no need that the expression `D()(p)` is well-formed at this point. I assume that the current wording is based on the corresponding `shared_ptr` wording. In case of `shared_ptr` this requirement is necessary, because the corresponding c'tor *can* fail and must invoke delete `p/d(p)` in this case. `Unique_ptr` is simpler in this regard. The *only* functions that must insist on well-formedness and well-definedness of the expression `get_deleter()(get())` are (1) the destructor and (2) `reset`. The reasoning for the wording change to explicitly require `DefaultConstructible` of `D` is to guarantee that invocation of `D`'s default c'tor is both well-formed and well-defined. Note also that we do *not* need the requirement that `T` must be complete, also in contrast to `shared_ptr`. `Shared_ptr` needs this, because it's c'tor is a template c'tor which potentially requires `Convertible<Y*, X*>`, which again requires Completeness of `Y`, if `!SameType<X, Y>` ]

4. Merge 20.3.1.3.2 [unique.ptr.single.ctor]/12+13 thereby removing the sentence of 12, but transferring the "requires" to 13:

   > Requires: If `D` is not an lvalue-reference type then[..]

   > [ N.B.: For the same reasons as for (3), there is no need that `d(p)` is well-formed/well-defined at this point. The current wording guarantees all what we need, namely that the initialization of both the `T*` pointer and the `D` deleter are well-formed and well-defined. ]

5. 20.3.1.3.2 [unique.ptr.single.ctor]/17: No changes necessary.

6. 20.3.1.3.2 [unique.ptr.single.ctor]/21:

   > Requires: If `D` is not a reference type, construction of the deleter `D` from an rvalue of type `E` shall be well formed and shall not throw an exception. If `D` is a reference type, then `E` shall be the same type as `D` (diagnostic required). `U*` shall be implicitly convertible to `T*`. [Note: These requirements imply that `T` and `U` be complete types. -- end note]

   [ N.B.: The current wording of 21 already implicitly guarantees that `U` is completely defined, because it requires that `Convertible<U*, T*>` is true. If the committee wishes this explicit requirement can be added, e.g. "`U` shall be a complete type." ]

7. 20.3.1.3.3 [unique.ptr.single.dtor]: Just before p1 add a new paragraph:

   > Requires: The expression `get_deleter()(get())` shall be well-formed, shall have well-defined behavior, and shall not throw exceptions. [Note: The use of `default_delete` requires `T` to be a complete type. -- end note]

   > [ N.B.: This requirement ensures that the whole responsibility on type-completeness of `T` is delegated to this expression. ]

8. 20.3.1.3.4 [unique.ptr.single.asgn]/1: No changes necessary, except the current editorial issue, that "must shall" has to be changed to "shall", but this change is not a special part of this resolution.

   [ N.B. The current wording is sufficient, because we can delegate all further requirements on the requirements of the effects clause ]

9. 20.3.1.3.4 [unique.ptr.single.asgn]/6:

   > Requires: Assignment of the deleter `D` from an rvalue `D` shall not throw an exception. `U*` shall be implicitly convertible to `T*`. [Note: These requirements imply that `T` and `U` be complete types. -- end note]

   [ N.B.: The current wording of p. 6 already implicitly guarantees that `U` is completely defined, because it requires that `Convertible<U*, T*>` is true, see (6)+(8). ]

10. 20.3.1.3.4 [unique.ptr.single.asgn]/11: No changes necessary.

    [ N.B.: Delegation to requirements of effects clause is sufficient. ]

11. 20.3.1.3.5 [unique.ptr.single.observers]/1+4+7+9+11:

    >     T* operator->() const;

    > > Note: Use typically requires `T` shall be complete. — end note]

12. 20.3.1.3.6 [unique.ptr.single.modifiers]/1: No changes necessary.

13. 20.3.1.3.6 [unique.ptr.single.modifiers]/4: Just before p. 4 add a new paragraph:

    > Requires: The expression `get_deleter()(get())` shall be well-formed, shall have well-defined behavior, and shall not throw exceptions.

14. 20.3.1.3.6 [unique.ptr.single.modifiers]/7: No changes necessary.

15. 20.3.1.4 [unique.ptr.runtime]: Add one additional bullet on paragraph 1:

    > A specialization for array types is provided with a slightly altered interface.

    > - ...
    > - `T` shall be a complete type.

[ post Bellevue: Daniel provided revised wording. ]