为什么reinterpret_cast不是 constexpr?
Why is reinterpret_cast not constexpr?
请考虑以下代码片段:
static constexpr uint8_t a = 0;
static constexpr const int8_t *b = reinterpret_cast<const int8_t *>(&a);
这无法用error: a reinterpret_cast is not a constant expression
编译,因为C++标准禁止在constexpr
中使用reinterpret_cast
。
但是,如果我想将值 b 存储在PROGMEM
中(对于 AVR 微控制器(,编译会成功:
static constexpr uint8_t a = 0;
static const int8_t PROGMEM *const b = reinterpret_cast<const int8_t *>(&a);
在这种情况下,编译器能够证明表达式reinterpret_cast<const int8_t *>(&a)
是编译时常量,因为它将其结果(指向包含零的某个字节的地址(插入到二进制文件的程序空间中:
_ZL1g:
.zero 1
.section .progmem.data,"a",@progbits
.type _ZL1b, @object
.size _ZL1b, 2
_ZL1b:
.word _ZL1g
另外,我的理解是reinterpret_cast
是一个编译时指令。那么为什么不能在constexpr
里面使用呢?
在运行时,C++语言具有未定义行为的概念。在某些(明确指定(条件下,程序具有未定义的行为,这意味着它可以表现出任何行为:它可以崩溃,它可以永远挂起,它可以打印乱码,它可以看起来工作,或者它可以做任何事情。为什么存在这种情况的简化解释是性能。
在运行时,这是一种权衡(如果您愿意的话,这是一种折衷(,但在编译时是不可接受的。如果标准允许在编译时使用 UB,不仅在编译程序或无限编译时崩溃是合法的,而且您永远无法确定编译的可执行文件的有效性。
因此,任何形式的constexpr
都必须 100% 没有未定义的行为。没有例外。没有回旋余地。
UB的一个臭名昭著的来源是reinterpret_cast
。reinterpret_cast
的有效用途很少,大多数都会导致UB。另外,几乎不可能检查使用是否有效。因此,在编译过程中不允许reinterpret_cast
,即在 constexpr 中不允许这样做。
那么为什么它不能在 constexpr 中使用呢?
仅仅因为标准不允许。 自 C++11 年以来,constexpr
一直是针对不同标准不断扩展的功能,因此很自然地认为reinterpret_cast
用途的子集可以工作。
问题是允许它是否真的有用或积极有害。reinterpret_cast
很少有好的用途,特别是如果你在严格的混叠规则成立的情况下编程和编译你的代码:很容易创建破坏它的指针。
另一方面,很明显,对于嵌入式用户和专门的编译器/标志/环境,它在某种程度上可能是有用的。
- 为什么std::isnan 不是 constexpr?
- 为什么reinterpret_cast不是 constexpr?
- 为什么我的 constexpr 对象在我的函数中不是 constexpr?
- 比较两个 constexpr 指针不是 constexpr?
- constexpr 函数在编译时获取值,即使我的变量不是 constexpr
- Constexpr变量不是编译时值
- 当迭代器(输入参数)通常不是constexpr时,constexpr算法真的有用吗
- 为什么非成员静态 constexpr 变量不是隐式内联的?
- const(但不是constexpr)用作内置数组大小
- 现在允许重新定义 constexpr 静态数据成员吗?(但不是内联常量)?
- std::可选的默认构造函数不是 gcc 中的 constexpr?
- __LINE__不是 MSVC 中的 constexpr
- 获取 constexpr 全局变量(不是静态成员)的链接器符号
- Clang声称通用lambda参数的constexpr成员不是constexpr
- Clang说is_same_v<int,double>的用法不是constexpr,不知道它怎么不是
- 为什么默认的构造函数在这里不是 constexpr
- constexpr(但不是真正的)构造函数在GCC中编译,而不是在Clang中编译
- 为什么可变参数函数模板中的这个 constexpr 不是常数?
- C++:为什么这个 constexpr 不是编译时常数
- 为什么constexpr不是自动的