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 likeshared_ptr
, but we are not comfortable with the wording. The specification forunique_ptr
should be more like that ofshared_ptr
. We need to know, for individual member functions, which ones require their types to be complete. Theshared_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
.
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. Aunique_ptr
owns the object it holds a pointer to. Aunique_ptr
is notCopyConstructible
, norCopyAssignable
, however it isMoveConstructible
andMoveAssignable
. The template parameterT
ofunique_ptr
may be an incomplete type. [ Note: The uses ofunique_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 ]
20.3.1.3.2 [unique.ptr.single.ctor]/1: No changes necessary.
[ N.B.: We only need the requirement that
D
isDefaultConstructible
. The current wording says just this. ]
In 20.3.1.3.2 [unique.ptr.single.ctor]/5 change the requires clause to say:
Requires:
The expressionD()(p)
shall be well formed. The default constructor ofD
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 correspondingshared_ptr
wording. In case ofshared_ptr
this requirement is necessary, because the corresponding c'tor *can* fail and must invoke deletep/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 expressionget_deleter()(get())
are (1) the destructor and (2)reset
. The reasoning for the wording change to explicitly requireDefaultConstructible
ofD
is to guarantee that invocation ofD
's default c'tor is both well-formed and well-defined. Note also that we do *not* need the requirement thatT
must be complete, also in contrast toshared_ptr
.Shared_ptr
needs this, because it's c'tor is a template c'tor which potentially requiresConvertible<Y*, X*>
, which again requires Completeness ofY
, if!SameType<X, Y>
]
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 theT*
pointer and theD
deleter are well-formed and well-defined. ]
20.3.1.3.2 [unique.ptr.single.ctor]/21:
Requires: If
D
is not a reference type, construction of the deleterD
from an rvalue of typeE
shall be well formed and shall not throw an exception. IfD
is a reference type, thenE
shall be the same type asD
(diagnostic required).U*
shall be implicitly convertible toT*
. [Note: These requirements imply thatT
andU
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."
]
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 ofdefault_delete
requiresT
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. ]
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 ]
20.3.1.3.4 [unique.ptr.single.asgn]/6:
Requires: Assignment of the deleter
D
from an rvalueD
shall not throw an exception.U*
shall be implicitly convertible toT*
. [Note: These requirements imply thatT
andU
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).
]
20.3.1.3.4 [unique.ptr.single.asgn]/11: No changes necessary.
[ N.B.: Delegation to requirements of effects clause is sufficient. ]
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]
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.
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. ]