提问人:Fedor 提问时间:11/21/2022 更新时间:11/24/2022 访问量:1491
一个可变 constexpr 变量可以在 C++ 中初始化另一个变量吗?
Can one volatile constexpr variable initialize another one in C++?
问:
C++ 标准允许每个缺陷报告 1688 的变量,该问题已于 2013 年 9 月解决:constexpr volatile
该组合是有意允许的,在某些情况下可用于强制恒定初始化。
看起来意图是只允许 ,这在 C++20 之前是不可用的。constinit volatile
尽管如此,当前的编译器在某些情况下的处理方式仍存在分歧。例如,此程序通过另一个变量初始化一个这样的变量: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 是正确的。
(...)允许使用Constexpr定义的非易失性对象“(...),但此类变量不能出现在常量表达式中。意图是什么?
但更有趣的是:为什么 Clang 关心而其他编译器却不在乎?
在我看来,发生这种情况是因为 JF Bastien,一个在 Clang / LLVM 世界中非常有影响力的人物,他个人不喜欢:)volatile
长期以来,他一直提议将其从语言中删除。因此,如果允许在某个地方禁止挥发性,他可能会不遗余力地做到这一点。如果没有其他原因,只是为了阻止人们编写代码,如果他的提议最终被接受,这些代码将不得不重写。
他还在 CppCon 上发表了关于他的弃用提案的演讲,如果你想知道他的理由。
评论
volatile
volatile
constexpr volatile
.rodata
const
volatile
volatile_load
volatile_store
constexpr
volatile
constexpr int x=123; constexpr int y=123;
Clang 是正确的。from 的初始化要求对 执行左值到右值的转换,但根据 [expr.const]/5.9,在常量表达式中绝不允许对 glvalue 进行左值到右值的转换。由于是一个变量,因此它必须由常量表达式初始化。j
i
i
volatile
i
constexpr
我不知道为什么 GCC 和 MSVC 选择不执行此规则,除了所有 C++ 编译器都永远人手不足,无法实现他们期望的一切。
评论
constexpr int x=someConstExpr;
constexpr
x
someConstExpr
constexpr
x
volatile,
volatile
x
y
x
y
x
volatile
x
constexpr
volatile
volatile
constexpr int two = 2; volatile int volatile_two = two;
constexpr
评论