2169. Missing reset() requirements in unique_ptr specialization

Section: 23.11.1.3.4 [unique.ptr.runtime.modifiers] Status: C++14 Submitter: Geoffrey Romer Opened: 2012-07-16 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [unique.ptr.runtime.modifiers].

View all issues with C++14 status.

Discussion:

In 23.11.1.3.4 [unique.ptr.runtime.modifiers]/p1-2 of N3376, the description of reset() in the array specialization of unique_ptr partially duplicates the description of the base template method (as specified in 23.11.1.2.5 [unique.ptr.single.modifiers]/p3-5), but lacks some significant requirements. Specifically, the text introduced in LWG 998, and item 13 of LWG 762, is present only in the base template, not the specialization.

This gives the appearance that these requirements specifically do not apply to the specialization, which I don't believe is correct or intended: the issue of reset() operation order addressed by LWG 998 applies just as much to the derived template as to the base template, and the derived template has just as much need to rely on get_deleter()(get()) being well-defined, well-formed, and not throwing exceptions (arguably some of those properties follow from the fact that T is required to be a complete type, but not all).

Assuming the derived template's reset() semantics are intended to be identical to the base template's, there is no need to explicitly specify the semantics of reset(pointer p) at all (since 23.11.1.3 [unique.ptr.runtime]/3 specifies "Descriptions are provided below only for member functions that have behavior different from the primary template."), and reset(nullptr_t p) can be specified by reference to the 'pointer' overload. This is more concise, and eliminates any ambiguity about intentional vs. accidental discrepancies.

[2012-10 Portland: Move to Ready]

This resolution looks blatantly wrong, as it seems to do nothing but defer to primary template where we should describe the contract here.

Ongoing discussion points out that the primary template has a far more carefully worded semantic for reset(p) that we would want to copy here.

STL points out that we need the nullptr overload for this dynamic-array form, as there is a deleted member function template that exists to steal overloads of pointer-to-derived, avoiding undifined behavior, so we need the extra overload.

Finally notice that there is blanket wording further up the clause saying we describe only changes from the primary template, so the proposed wording is in fact exactly correct. Move to Ready.

[2013-04-20 Bristol]

Proposed resolution:

This wording is relative to N3376.

Change 23.11.1.3.4 [unique.ptr.runtime.modifiers] as indicated:

void reset(pointer p = pointer()) noexcept;
void reset(nullptr_t p) noexcept;

-1- Effects: If get() == nullptr there are no effects. Otherwise get_deleter()(get()) Equivalent to reset(pointer()).

-2- Postcondition: get() == p.