Destructors and noexcept
Since we have noexcept
in the language, destructors are implicitly noexcept
. One interesting part here is that this statement is true for user-defined destructors as well as for defaulted or the implicitly generated destructor. The user-defined case is interesting. We have an implicit noexcept
here.
The relevant references in the standard are:
[class.dtor] p6: Note: A declaration of a destructor that does not have a noexcept-specifier has the same exception specification as if it had been implicitly declared (14.5).
and
[except.spec] p8: The exception specification for an implicitly-declared destructor, or a destructor without a noexcept-specifier, is potentially-throwing if and only if any of the destructors for any of its potentially constructed subobjects is potentially throwing or the destructor is virtual and the destructor of any virtual base class is potentially-throwing.
All right, nice, but why I'm telling you this? Well, for a long time, C++ Insight was showing, say, interesting results. In C++ Insights, the defaulted destructor did not show up as noexcept
if we didn't use it. Use here means creating an object of this type. Consider the following example:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
The resulting transformation was this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
The destructor of UserProvided
is shown with noexcept
, but the destructor of Defaulted
isn't. What's interesting, and what was confusing to me, is that down in main
, I created an object of Defaulted
, and the destructor did still not show up as noexcept
The output changed once Defaulted
contained a member requiring destruction, like UserProvided
. Below is the result of a transformation with C++ Insights.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
As you can see, I added a member val
of type UserProvided
to Defaulted
. I didn't touch the destructor of Defaulted
. But in the transformation, the destructor does not carry the noexcept
.
That behavior itself isn't totally surprising. At least Clang does only the minimum in a lot of places, saving us compile times. If an object doesn't require a destructor, why border with figuring out the exception specification? I did overlook this delay for quite a while until we talked about exactly such a case in one of my training classes, and I failed to demonstrate with C++ Insights what's going on. My apologies to the participants of this class! I should have known it, but the output of my own app confused med.
I recently added a fix for this case. You will now see a noexcept
comment: /* noexcept */
indicating that this destructor is potentially noexcept
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Please let me know the issue you find in C++ Insights!
Support the project
You can support the project by becoming a GitHub Sponsor or, of course, with code contributions.
Andreas