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
. i.e. 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 y.h in x.h 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 x.h:
#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 y.h:
#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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With