一个volatile constexpr变量可以在c++中初始化另一个变量吗?



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,volatileglvalue的左值到右值的转换在常量表达式中是不允许的。由于iconstexpr变量,因此必须使用常量表达式对其进行初始化。

我不知道为什么GCC和MSVC选择不执行这条规则,除了所有的c++编译器永远都是人手不足的,不能实现他们所期望的一切。

您链接的缺陷报告显示它不应该工作,所以Clang是正确的。

(…)"用constexpr定义的非易失性对象"(…)是允许的,但是这样的变量不能出现在常量表达式中。目的是什么?

但更有趣的是:为什么Clang关心而其他编译器不关心?

在我看来,这是因为JF Bastien, Clang/LLVM世界中一个非常有影响力的人物,他个人不喜欢volatile:)

他一直建议从语言中删除它很长一段时间。因此,如果允许在某个地方禁止挥发性,他可能会不遗余力地做到这一点。如果没有其他原因,只是为了防止人们编写代码,如果他的建议最终被接受,这些代码将不得不重写。

如果你想知道他的理由,他还在CppCon上做了一个关于他的弃用建议的演讲。

最新更新