c++标准允许constexpr volatile
变量每个缺陷报告1688,这是在2013年9月解决的:
这种组合是有意允许的,在某些情况下可以用来强制常量初始化。
看起来意图是只允许constinit volatile
,这在c++ 20之前是不可用的。
目前的编译器在某些情况下对constexpr volatile
的处理仍然存在分歧。例如,下面这个程序用另一个变量初始化一个这样的变量:
int main() {
constexpr volatile int i = 0;
constexpr volatile int j = i;
return j;
}
它在GCC和MSVC中被接受,但是Clang抱怨:
error: constexpr variable 'j' must be initialized by a constant expression
constexpr volatile int j = i;
^ ~
note: read of volatile-qualified type 'const volatile int' is not allowed in a constant expression
constexpr volatile int j = i;
在线演示:https://gcc.godbolt.org/z/43ee65Peq
哪个编译器在这里,为什么?
Clang是正确的。从i
初始化j
需要在i
上执行左值到右值的转换,但是根据[exp .const]/5.9,volatile
glvalue的左值到右值的转换在常量表达式中是不允许的。由于i
是constexpr
变量,因此必须使用常量表达式对其进行初始化。
我不知道为什么GCC和MSVC选择不执行这条规则,除了所有的c++编译器永远都是人手不足的,不能实现他们所期望的一切。
您链接的缺陷报告显示它不应该工作,所以Clang是正确的。
(…)"用constexpr定义的非易失性对象"(…)是允许的,但是这样的变量不能出现在常量表达式中。目的是什么?
但更有趣的是:为什么Clang关心而其他编译器不关心?
在我看来,这是因为JF Bastien, Clang/LLVM世界中一个非常有影响力的人物,他个人不喜欢volatile
:)
他一直建议从语言中删除它很长一段时间。因此,如果允许在某个地方禁止挥发性,他可能会不遗余力地做到这一点。如果没有其他原因,只是为了防止人们编写代码,如果他的建议最终被接受,这些代码将不得不重写。
如果你想知道他的理由,他还在CppCon上做了一个关于他的弃用建议的演讲。