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

vatpfxk5  于 2022-11-27  发布在  其他
关注(0)|答案(2)|浏览(99)

根据缺陷报告1688,C标准允许constexpr volatile变量,该问题已于2013年9月解决:
这种组合是有意允许的,在某些情况下可用于强制常量初始化。
它看起来只允许constinit volatile,这在C
20之前是不可用的。
在某些情况下,当前的编译器在处理constexpr volatile时仍然存在分歧。例如,下面的程序用一个变量初始化另一个变量:

int main() {
    constexpr volatile int i = 0;
    constexpr volatile int j = i;
    return j;
}

愚者和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
这里是哪种编译器?为什么?

b09cbbtk

b09cbbtk1#

Clang是正确的。从i初始化j需要在i上执行左值到右值的转换,但根据[expr.const]/5.9,在常量表达式中不允许在volatile glvalue上执行左值到右值的转换。由于iconstexpr变量,因此必须由常量表达式初始化它。
我不知道为什么愚者和MSVC选择不执行这一规则,除了所有的C++编译器总是人手不足,不能实现他们期望的一切。

8cdiaqws

8cdiaqws2#

您链接的缺陷报告显示它不应该工作,因此Clang正确。
(...)允许“使用constexpr定义的非易失性对象”(...),但此类变量不能出现在常量表达式中。其意图是什么?
但更有趣的是:为什么Clang关心而其他编译器不关心呢?
在我看来,这是因为JF Bastien,一个在Clang / LLVM世界里非常有影响力的人物,他个人不喜欢volatile:)
他已经proposing to remove它从语言很长一段时间。所以如果它被允许禁止volatile某处,他可能不遗余力地使它如此。如果没有其他原因,只是为了防止人们写的代码,将不得不重写,如果他的建议最终被接受。
如果你想知道他的推理,他还在CppCon上做了一个关于他的deprecation proposal的演讲。

相关问题