Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[unique.ptr] Clarify nullptr case in destructor and reset() #2962

Closed

Conversation

chradcliffe
Copy link

In unique_ptr::~unique_ptr and unique_ptr::reset, the Requires statements are ambiguous about whether get_deleter()(nullptr) should have well-defined behaviour.

From the Effects statements for both specifications, it's clear that get_deleter(get()) is not called in the case where the unique_ptr contains nullptr. This fix makes it clear that get_deleter(nullptr) is not required to have well-defined behaviour.

Copy link
Member

@jwakely jwakely left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This use of "well-formed" is a syntactic requirement, it says the expression must compile. It places no requirements on the value of get(), and it doesn't make sense to say it only needs to be well-formed for certain values. So this change is wrong.

@chradcliffe
Copy link
Author

chradcliffe commented Jul 9, 2019

@jwakely in my proposed change, there's no change to the applicability of "well-formed". The change is to the applicability of "well-defined behavior" in the case where the unique_ptr contains a nullptr. If I understand the standardese correctly, "well-defined behavior" can be dependent on runtime values.

@jwakely
Copy link
Member

jwakely commented Jul 9, 2019

Doh, you're quite right, I misread the diff, sorry.

@jwakely
Copy link
Member

jwakely commented Jul 9, 2019

Now that I've remembered how to read, I think the "shall not throw exceptions" requirement should only apply to the get() != nullptr case. The deleter is allowed to throw exceptions in the general case, just not when invoked by unique_ptr.

@jwakely
Copy link
Member

jwakely commented Jul 9, 2019

Thanks for the update.

It might be easier to use the new specification structure that the standard library clauses are migrating to:

Mandates: The expression get_deleter()(get()) is well-formed.

Expects: If get() != nullptr, the expression get_deleter()(get()) has well-defined behavior and does not throw exceptions.

But somebody else is already working on doing that.

Whichever structure we use, this is a requirement that says "if this expression isn't well-defined, then it's undefined", which is a tautology. The "shall not throw" part is still useful though.

@chradcliffe
Copy link
Author

I stumbled across this because I was curious as to whether the standard required a null check on the part of the deleter. I think it's still helpful to say that there is no requirement for get_deleter()(nullptr) to have well-defined behaviour. Is there maybe a better way of expressing that?

@jensmaurer
Copy link
Member

Well, you could add a note (as in "[Note: blah -- end note]") to say that the result of get_deleter() is never invoked with a null pointer value, and thus no requirements are imposed on the deleter for that argument value.

@CaseyCarter
Copy link
Contributor

CaseyCarter commented Jul 9, 2019

Were I to specify these destructors in a green field, I'd write simply:

Effects: Equivalent to: if (get()) get_deleter()(get());

and not bother with explicit requirements.

(Note that "no effects" is just as wrong here as virtually every place we use it in the Library: pointer can be a user-defined type, so the null test is a user-observable effect.)

@jensmaurer
Copy link
Member

@CaseyCarter, I fully agree. However, introducing "Equivalent to" in an editorial issue is usually ... not what we do. @zygoloid?

@jensmaurer jensmaurer changed the title Clarify nullptr case in ~unique_ptr/unique_ptr::reset [unique.ptr] Clarify nullptr case in destructor and reset() Jul 9, 2019
@jensmaurer jensmaurer added the needs rebase The pull request needs a git rebase to resolve merge conflicts. label Sep 30, 2019
@jensmaurer
Copy link
Member

Please rebase and fix the conflicts, then force-push.

In `unique_ptr::~unique_ptr` and `unique_ptr::reset`, the Requires statements are ambiguous about whether `get_deleter()(nullptr)` should have well-defined behaviour.

From the Effects statements for both specifications, it's clear that `get_deleter(get())` is not called in the case where the `unique_ptr` contains `nullptr`. This fix makes it clear that `get_deleter(nullptr)` is not required to have well-defined behaviour.
@jensmaurer
Copy link
Member

Superseded by #4736

@chradcliffe chradcliffe closed this Jul 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs rebase The pull request needs a git rebase to resolve merge conflicts.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants