简体   繁体   English

为什么 reinterpret_cast 不是 constexpr?

[英]Why is reinterpret_cast not constexpr?

Consider the following snippet:考虑以下片段:

static constexpr uint8_t a = 0;
static constexpr const int8_t *b = reinterpret_cast<const int8_t *>(&a);

This fails to compile with error: a reinterpret_cast is not a constant expression , because the C++ standard forbids using reinterpret_cast in constexpr .这无法编译并error: a reinterpret_cast is not a constant expression ,因为C++ 标准禁止constexpr使用reinterpret_cast

However compilation succeeds if I want to store the value b in PROGMEM (for AVR microcontrollers):但是,如果我想将值 b 存储在PROGMEM (对于 AVR 微控制器),则编译会成功:

static constexpr uint8_t a = 0;
static const int8_t PROGMEM *const b = reinterpret_cast<const int8_t *>(&a);

In this case the compiler is able to prove that the expression reinterpret_cast<const int8_t *>(&a) is compile-time constant, since it inserts its result (an address pointing to some byte containing a zero) into program space in the binary:在这种情况下,编译器能够证明表达式reinterpret_cast<const int8_t *>(&a)是编译时常量,因为它将其结果(指向包含零的某个字节的地址)插入到二进制程序空间中:

_ZL1g:
  .zero   1
  .section        .progmem.data,"a",@progbits
  .type   _ZL1b, @object
  .size   _ZL1b, 2
_ZL1b:
  .word   _ZL1g

Also, my understanding is that reinterpret_cast is a compile-time directive.另外,我的理解是reinterpret_cast是一个编译时指令。 So how come it can't be used inside a constexpr ?那么为什么它不能在constexpr呢?

At runtime the C++ language has the concept of Undefined Behavior.在运行时,C++ 语言具有未定义行为的概念。 Under certain (well specified) conditions, the program has Undefined Behavior, that means that it can exhibit any behavior: it can crash, it can hang forever, it can print gibberish, it can appear to work, or it can do anything.在某些(明确指定的)条件下,程序具有未定义的行为,这意味着它可以表现出任何行为:它可以崩溃,它可以永远挂起,它可以打印胡言乱语,它可以看起来工作,或者它可以做任何事情。 A simplified explanation of why this exists is performance.为什么会出现这种情况的一个简单解释是性能。

At runtime this is a tradeoff (a compromise if you will), but it is unacceptable at compile time.在运行时,这是一种折衷(如果您愿意,可以进行折衷),但在编译时这是不可接受的。 If the standard would allow UB at compile time, not only it would be legal to get crashes while compiling the program or compile ad infinitum, but you could never be sure of the validity of the compiled executable.如果标准允许在编译时使用 UB,那么不仅在编译程序或无限编译时发生崩溃是合法的,而且您永远无法确定编译后的可执行文件的有效性。

As such, any form of constexpr would have to be 100% free of Undefined Behavior.因此,任何形式的constexpr都必须 100% 没有未定义行为。 No exceptions about it.没有例外。 No leeway.没有余地。

One notorious source of UB is reinterpret_cast . UB 的一个臭名昭著的来源是reinterpret_cast There are very few valid uses of reinterpret_cast , most of them result in UB. reinterpret_cast有效用途很少,大多数都会导致 UB。 Plus it is practically impossible to check if the use is valid.此外,几乎不可能检查使用是否有效。 So reinterpret_cast is not allowed during compilation, ie it is not allowed in constexpr.所以在编译期间不允许reinterpret_cast ,即在 constexpr 中是不允许的。

So how come it can't be used inside a constexpr?那么为什么它不能在 constexpr 中使用呢?

Simply because the standard does not allow it.仅仅是因为标准不允许。 constexpr has been a feature that has been ever expanding since C++11 over the different standards, so it is natural to think that a subset of reinterpret_cast uses could work.自 C++11 以来, constexpr一直是一个不断扩展的功能,适用于不同的标准,因此很自然地认为reinterpret_cast使用的一个子集可以工作。

The question is whether allowing it would be actually useful or actively harmful.问题是允许它实际上是有用的还是有害的。 There are very few good uses of reinterpret_cast , specially if you program and compile your code assuming the strict aliasing rule holds: it would be easy to create pointers that break it. reinterpret_cast很少有好的用途,特别是如果你编程和编译你的代码时假设严格的别名规则成立:很容易创建破坏它的指针。

On the other hand, it is clear that, for embedded users and specialized compilers/flags/environments, it could be useful to some degree.另一方面,很明显,对于嵌入式用户和专门的编译器/标志/环境,它在某种程度上可能是有用的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM