constexpr变量是否需要“静态初始化顺序失败”?

Lot*_*ney 5 c++ initialization global-variables constexpr

如果我初始化constexpr变量foo在一个翻译单元,其具有非缺省值,然后一个初始化另一个constexpr变量barfoo在另一翻译单元有可能是bar之前被初始化foo导致bar,是由初始化为零或缺省初始化foo。即与在非constexpr情况下(静态初始化顺序彻底失败有效)不同,编译器和链接器是否将分析依赖性顺序以确保正确的结果?

另外,constexpr变量模板如何受到影响?在单个翻译单元中,它们的初始化顺序是不确定的。

首选C ++ 17标准答案。

更新:这是一个最小的示例。有用; 那就是问题所在。至此,我99%确信这可以通过静态初始化命令惨败(TSIOF)来解决。但是,由于该问题的极端,阴险性质,我需要确认这是可以的。我相信该代码不会受到TSIOF的困扰,因为在xh命令abx.cc转换单元中包含了yh 。但是,AFAIU有2个翻译单元:一个包含a,另一个包含b。此外,AFAI-sort-of-U对a错误的多重定义不会出现,因为static关键字具有内部链接,a仍然具有全局范围

编译为:

clang++ -std=c++17 x.cc y.cc  #or g++
Run Code Online (Sandbox Code Playgroud)

可能的输出:

in foo
Run Code Online (Sandbox Code Playgroud)

可能的输出:

assertion failed (core dumped)
Run Code Online (Sandbox Code Playgroud)

文件x.cc:

#include "x.h"
int main(){ assert(b == 42); foo(); }
Run Code Online (Sandbox Code Playgroud)

文件xh:

#pragma once
#include "y.h"
static constexpr int b = a+1;
Run Code Online (Sandbox Code Playgroud)

文件y.cc:

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

档案yh:

#pragma once
static constexpr int a=41;
void foo();
Run Code Online (Sandbox Code Playgroud)

这个程序可以保证输出in foo吗?

由于无法通过示例回答此问题,因此确实需要语言律师来提供相关的标准报价

这个问题是关于跨翻译单位的STIOF。有关模板变量的翻译单元内的STIOF的一个相关的,未回答的问题在这里

小智 5

在您的示例中,不存在可能的问题,因为y.cc 中的变量与x.cc 中的a变量不同。a所以没有发生跨翻译单元链接。

\n\n

事实上, constexpr 变量之间不能存在交叉翻译单元链接。要点在于constexpr该值是在编译时计算的。

\n\n

换句话说,当我们仍在单独编译翻译单元时,constexpr 必须解析为一个值。

\n\n

因此,静态初始化顺序失败隐式不适用于constexpr变量,并且标准不需要提及在这种情况下要做什么。

\n\n

编辑:根据要求,标准的相关部分是 10.1.5 (9)[dcl.constexpr]

\n\n
\n

在任何 constexpr 变量声明中,初始化的完整表达式应为常量表达式 (8.20)。

\n
\n\n

这导致 8.20 (1) [expr.const] 具有以下注释:

\n\n
\n

[ 注意:常量表达式可以在翻译过程中求值。\xe2\x80\x94 尾注]

\n
\n\n

这是下一页半条款背后的基本原理,但其本身足以排除交叉翻译单元引用。

\n