constexpr模板变量的初始化顺序是否有明确标准保证?
无序动态初始化仅适用于未显式特化的(静态/线程局部)类模板静态数据成员和变量模板(C++14起)。
根据这段内容,未显式特化的静态/线程局部模板静态数据成员、变量模板,在动态初始化阶段是没有顺序保证的,这也让这类静态模板变量更容易陷入严重的静态初始化顺序问题(Static Initialization Order Fiasco, TSIOF)——也就是同一翻译单元内的初始化顺序是无序的。
那如果改用constexpr修饰这类静态模板变量,能否彻底消除这个风险?比如下面这段代码,输出是否必然是success?
#include<cassert> #include<iostream> template<class T> static constexpr T a = 41; template<class T> static constexpr T b = a<T>+1; int main(){ assert(b<int> == 42); std::cout <<"success\n"; }
显然,这类标准层面的问题没法靠运行示例来验证,必须从C标准(优先C17)的规定入手分析。
核心疑问澄清
我需要明确我的核心关注点:我并不关心示例代码会不会触发动态初始化(实际上并不会),而是担心一个本质问题——既然动态初始化场景下这类变量没有有序保证,那常量初始化场景下,我们能不能100%信赖初始化的顺序?
在了解动态初始化的静态生存期模板变量的行为之前,我从未考虑过这个问题,但既然动态初始化的这类变量没有顺序保证,我也没有理由默认常量初始化的静态生存期模板变量就一定有顺序保证。我需要确凿的答案:同一翻译单元(TU)内,模板变量的常量初始化是否严格按照定义顺序执行?
我甚至有这样的顾虑:如果编译器在处理动态初始化时不需要遵循顺序,那处理常量初始化时也可能不强制顺序——毕竟标准没明确说常量初始化是无序的,但仅仅“没说无序”似乎不足以让我完全放心。
可能有人觉得这种担忧是过度谨慎,但我正在开发安全关键软件,公司已经暂停采用C++14,直到这个问题得到明确的答案。
另外,还有一个相关的未解决疑问:如果跨翻译单元时,constexpr变量依然无法解决静态初始化顺序问题,这会给安全关键软件的开发带来怎样的影响?
内容的提问来源于stack exchange,提问作者Lotney

