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_ptrmore likeshared_ptr, but we are not comfortable with the wording. The specification forunique_ptrshould be more like that ofshared_ptr. We need to know, for individual member functions, which ones require their types to be complete. Theshared_ptrspecification 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_ptrprovides a semantics of strict ownership. Aunique_ptrowns the object it holds a pointer to. Aunique_ptris notCopyConstructible, norCopyAssignable, however it isMoveConstructibleandMoveAssignable. The template parameterTofunique_ptrmay be an incomplete type. [ Note: The uses ofunique_ptrinclude 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
DisDefaultConstructible. 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 ofDshall not throw an exception.Dmust not be a reference type.Dshall 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_ptrwording. In case ofshared_ptrthis requirement is necessary, because the corresponding c'tor *can* fail and must invoke deletep/d(p)in this case.Unique_ptris 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 requireDefaultConstructibleofDis 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 thatTmust be complete, also in contrast toshared_ptr.Shared_ptrneeds 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
Dis 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 theDdeleter are well-formed and well-defined. ]
20.3.1.3.2 [unique.ptr.single.ctor]/21:
Requires: If
Dis not a reference type, construction of the deleterDfrom an rvalue of typeEshall be well formed and shall not throw an exception. IfDis a reference type, thenEshall be the same type asD(diagnostic required).U*shall be implicitly convertible toT*. [Note: These requirements imply thatTandUbe 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_deleterequiresTto be a complete type. -- end note][ N.B.: This requirement ensures that the whole responsibility on type-completeness of
Tis 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
Dfrom an rvalueDshall not throw an exception.U*shall be implicitly convertible toT*. [Note: These requirements imply thatTandUbe 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
Tshall 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.
- ...
Tshall be a complete type.
[ post Bellevue: Daniel provided revised wording. ]