C++ Logo

std-proposals

Advanced search

[std-proposals] Relax condition for potentially invoked destructor via noexcept

From: Kilian Henneberger <kilis-mail_at_[hidden]>
Date: Thu, 28 Sep 2023 14:14:10 +0200
Hello everyone,

last year I started a thread in this mailing list: [std-proposals] Relax condition for potentially invoked destructor in constructor.

I aimed at adjusting
https://eel.is/c++draft/class.base.init#12. Right now the wording says that the destructor for each potentially constructed subobject is potentially invoked. And the wording requires this unconditionally. I wanted to add conditions, under which the destructor of each potentially constructed object is potentially invoked. Given following class:


struct S {
    std::unique_ptr<class Impl> pimpl;
    S() : pimpl() {}
};


We know, that after the construction of
pimpl, the constructor of S has nothing else to do and, especially, will never throw anything. Therefore we never actually have to invoke the destructor of pimpl from within the constructor of S. But as of now, the wording requires that the destructor of pimpl is potentially invoked in the constructor of S. Therefore the code won't compile as trying to invoke pimpl's destructor requires Impl to be a complete type which it isn't at that point. As you can deduce from my example, I aim at making the PImpl idiom easier to apply.

Last year I received valuable feedback on this mailing list.
A) While I only mentioned
https://eel.is/c++draft/class.base.init#12, Lénárd Szolnoki pointed out that I should also take a look at https://eel.is/c++draft/stmt.return#3, which has a similar wording for similar reasons and could similarly be adjusted. There are further places in the standard, which require a destructor to be potentially invoked. For completeness I list them all here:
https://eel.is/c++draft/class.base.init#12
https://eel.is/c++draft/expr.new#25
https://eel.is/c++draft/stmt.return#3
https://eel.is/c++draft/dcl.init.aggr#9
https://eel.is/c++draft/except.throw#5
I think the only relevant ones are [class.base.init#12] and [stmt.return#3].

B)
Jason McKesson gave the valuable feedback that my original idea makes "potentially invoked" a matter of exactly how you initialize an object, which sounds very brittle. And I agree. Therefore I am proposing an alternative idea: Instead of making "potentially invoked" a matter of how you initialize an object and which other subobjects might get initialized afterwards, we use
noexcept as measure to decide whether destructors are potentially invoked within a constructor. So if a constructor is marked noexcept, we know that there is no way for an exception to be thrown out of that constructor. Therefore, we also have no need for the destructors of potentially constructed subobjects to be invoked. Addressing https://eel.is/c++draft/stmt.return#3 would work in a similar way: The destructor for the result object of a function should only be potentially invoked if the function is not marked noexcept.

Thanks for reading this long mail and I would highly appreciate your feedback.

Cheers,
Kilian

Received on 2023-09-28 12:14:12