即使在 C++20 中, std::memcpy 也不是 constexpr 的原因是什么?

Qui*_*mby 13 c++ constexpr c++20

我知道在编译时复制任意内存块并不总是可能的,但既然我们得到了 constexpr 容器、虚拟方法和算法,为什么不也复制 memcpy 呢?这也是一种算法。

\n

此外,

\n
    \n
  • C++20std::bit_cast看起来很像std::memcpy解决方法reinterpret_cast,但它确实是constexpr
  • \n
  • std::copy使用迭代器被标记为constexprC++20,因此对于类型来说复制是可能的。
  • \n
\n

用法是复制或只是“重新解释”constexpr函数中的变量/数组,据我所知,前者没有解决std::bit_cast。特别是这个问题和我的答案想用它。

\n
    \n
  • 为什么std::bit_cast可以是 constexpr 而std::memcpy不能是有什么特殊原因吗?
  • \n
  • 它与使用 void 指针而不是类型化引用的 memcpy 有关吗?
  • \n
  • 实际上不需要复制任何东西吗?
  • \n
  • C向后兼容?
  • \n
  • 也许是因为不支持“指向 constexpr 内存的指针”?但这同样适用于 中的引用参数std::bit_cast和 中的迭代器std::copy
  • \n
\n

C++20 bit_cast vs reinterpret_cast的相关答案简要引用于某处:

\n
\n

此外,目前不可能实现 constexpr\n位转换函数,因为 memcpy 本身不是 \xe2\x80\x99t constexpr。将提议的函数标记为 constexpr 不需要或阻止 memcpy 变成 constexpr,但需要编译器支持。这使得实现可以自由地使用自己的内部解决方案(例如 LLVM 具有位播操作码)。

\n
\n

但它没有详细讨论不使其成为 constexpr 的细节。

\n

请注意,我不会问为什么std::bit_cast存在。我喜欢它,它提供了明确的意图而不是std::memcpy解决方法。

\n

Nic*_*las 8

运行时代码中的 C++ 对象模型通常处理得比较宽松。它有相当严格的规则,但有很多后门要么被允许,要么被声明为 UB。后者意味着您仍然可以编写代码来执行此操作,但 C++ 不保证该代码的行为。

在持续评估(又名:代码的编译时执行)中,情况并非如此。这些限制constexpr是专门为了让对象模型成为您必须遵循的真实事物而没有可行的后门。即使它偶尔允许的那些也明确要求格式错误并产生编译错误,而不是静默 UB。

基本上在运行时,您可以将内存视为存储字节。在编译时,你不能;你不被允许这样做。即使constexpr在 C++20 中添加了动态分配代码,您也无法玩很多通常玩此类游戏的游戏。

memcpy以字节为单位进行存储,来回​​复制它们而不知道它们的含义。bit_cast 知道源对象和目标对象,并且除非源对象和目标对象适合bit_casting(即:可简单复制),否则它不会允许您执行此操作。

bit_cast如果您希望它在编译时工作,则对这两个对象的内容也有非常具体的限制。特别是,您不能使用指针或任何包含任何类型指针的对象。或者参考文献。bit_cast

这是因为编译时的指针不仅仅是地址。为了捕获 UB,编译时指针必须知道它指向的对象的真实动态类型。因此,在编译时不允许仅转换地址的指针转换。