简体   繁体   中英

Is the “static initialization order fiasco” a concern for constexpr variables?

If I initialize a constexpr variable foo with a non-default value in one translation unit and then a initialize another constexpr variable bar with foo in another translation unit is it possible for bar to be initialized before foo resulting in a bar that was initialized by a zero-or-default-initialized foo . ie Unlike in the non-constexpr case (where the static initialization order fiasco is in effect) will the compiler and linker analyze dependency ordering to guarantee the correct result?

Additionally, how are constexpr variable templates affected? Their initialization ordering is undefined WITHIN single translation units.

C++17 standard answers preferred.

UPDATE: Here is a minimal example. It works; that's the problem. At this point I'm 99% sure that this is safe from The Static Initialization Order Fiasco (TSIOF) . However, due to the extreme, insidious nature of that problem I need to get confirmation that this is ok. I believe this code does not suffer from TSIOF since the inclusion of yh in xh orders a and b within the x.cc translation unit. However, AFAIU there are 2 translation units: one containing a, the other containing b. Furthermore, AFAI-sort-of-U a multiple definition of a error does not arise because the static keyword imparts internal linkage but a still has global scope .

compiled with:

clang++ -std=c++17 x.cc y.cc  #or g++

possible output:

in foo

possible output:

assertion failed (core dumped)

file x.cc:

#include "x.h"
int main(){ assert(b == 42); foo(); }

file xh:

#pragma once
#include "y.h"
static constexpr int b = a+1;

file y.cc:

#include "y.h"
#include <iostream>
void foo(){
    std::cout << " in foo \n";
}

file yh:

#pragma once
static constexpr int a=41;
void foo();

Is this program guaranteed to output in foo ?

Since this question can't be answered via example it really needs a language lawyer to provide relevant standard quotes

This question is about STIOF across translation units. A related, unanswered question about STIOF within translation units for template variables is here

In your example, there is no possible issue because the a in y.cc is a different variable from a in x.cc. So there is no cross-translation unit linkage happening.

In fact, there cannot be cross-translation unit linkage between constexpr variables. The whole point of constexpr is that the value is calculated at compilation time.

In other words, the constexpr must resolve to a value while we are still compiling the translation unit in isolation.

Because of the this the Static Initialization Order Fiasco implicitly does not apply to constexpr variables, and there is no need for the standard to mention what to do in that scenario.

Edit: as requested, the relevant part of the standard is 10.1.5 (9)[dcl.constexpr]

In any constexpr variable declaration, the full-expression of the initialization shall be a constant expression (8.20).

Which leads to 8.20 (1) [expr.const] that has the following note:

[ Note: Constant expressions can be evaluated during translation. — end note ]

Which is the rationale behind the next page and a half of clauses, but is enough by itself to preclude cross-translation unit references.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM