A recent question drew my attention to the way that constexpr
has changed in C++14. The new feature is that a non-local variable with static storage duration may be initialized in the static initialization phase if its initializer consists of a constexpr
constructor, even if the type of the variable isn't a literal type. More precisely, the new wording in [basic.start.init] is:
A constant initializer for an object
o
is an expression that is a constant expression, except that it may also invoke constexpr constructors foro
and its subobjects even if those objects are of non-literal class types [Note: such a class may have a non-trivial destructor — end note]. Constant initialization is performed [...] if an object with static or thread storage duration is initialized by a constructor call, and if the initialization full-expression is a constant initializer for the object [...]
The typical example is std::unique_ptr
, which "should never be worse that hand-written":
std::unique_ptr<int> p; // statically initialized by [unique.ptr.single.ctor],
// requires no code excution
int main()
{
p = std::make_unique<int>(100);
}
// p is destroyed eventually
Prior to this addition, statically initialized variables were either of reference type or of literal object type, and therefore had trivial destructors. But now a statically initialized global variable can have a non-trivial destructor.
How is such a destructor call ordered with respect to the destructors of dynamically initialized global objects, with respect to other statically initialized ones, and how are the destructor calls sequenced?
[basic.start.term]/1
(N4140) says:As I understand, this means that for the purpose of determinig the order of destruction, all static initialization is treated as dynamic (ordered or unordered) and the destructors are called in reverse order of this initialization.