Does the C++ standard guarantee that uniform initialization is exception-safe?

It seems so:

Curiously found in §6.6/2 Jump Statements [stmt.jump] of all places (N4618):

On exit from a scope (however accomplished), objects with automatic
storage duration (3.7.3) that have been constructed in that scope are
destroyed in the reverse order of their construction. [ Note: For
temporaries, see 12.2. —end note ] Transfer out of a loop, out of a
block, or back past an initialized variable with automatic storage
duration involves the destruction of objects with automatic storage
duration that are in scope at the point transferred from but not at
the point transferred to. (See 6.7 for transfers into blocks). [ Note:
However, the program can be terminated (by calling std::exit() or
std::abort() (18.5), for example) without destroying class objects
with automatic storage duration. —end note ]

I think the emphasis here is on the “(however accomplished)” part. This includes an exception (but excludes things that cause a std::terminate).


EDIT

I think a better reference is §15.2/3 Constructors and destructors [except.ctor] (emphasis mine):

If the initialization or destruction of an object other than by
delegating constructor is terminated by an exception, the destructor
is invoked for each of the object’s direct subobjects
and, for a
complete object, virtual base class subobjects, whose initialization
has completed (8.6) and whose destructor has not yet begun execution,
except that in the case of destruction, the variant members of a
union-like class are not destroyed. The subobjects are destroyed in
the reverse order of the completion of their construction. Such
destruction is sequenced before entering a handler of the
function-try-block of the constructor or destructor, if any.

This would include aggregate initialization (which I learned today can be called non-vacuous initialization)

…and for objects with constructors we can cite §12.6.2/12 [class.base.init](emphasis mine):

In a non-delegating constructor, the destructor for each potentially
constructed subobject of class type is potentially invoked (12.4). [
Note: This provision ensures that destructors can be called for
fully-constructed subobjects in case an exception is thrown
(15.2).
—end note ]

Leave a Comment

tech