Std::Memcpy即使在C++20中也不是常量的原因是什么?

2022-05-16 00:00:00 c++ c++20 constexpr

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

更多,

  • C++20std::bit_cast看起来很像std::memcpy解决办法reinterpret_cast,但它确实是constexpr
  • std::copy对于C++20,使用迭代器被标记为constexpr,因此可以以某种方式复制类型。
的用法是复制或仅复制constexpr函数中的变量/数组,前者不能通过std::bit_castAFAIK解决。特别是,question和我的答案都想用它。

  • std::bit_cast可以是常量,std::memcpy不能是常量有什么特殊原因吗?
  • 是否与使用空指针而不是类型化引用的Memcpy有关?
  • 实际上不必复制任何内容?
  • C向后兼容?
  • 可能是因为不支持指向常量内存的";指针?但这同样适用于std::bit_cast中的引用参数和std::copy中的迭代器。

对C++20 bit_cast vs reinterpret_cast的相关回答从某处简要引用:

此外,目前不可能实现constexpr 位转换函数,因为Memcpy本身不是常量表达式。标志着 建议的函数,因为Constexpr不需要或阻止Memcpy 成为conexpr,但需要编译器支持。这片树叶 可自由使用自己的内部解决方案的实施(例如,LLVM具有 位广播操作码)。

但没有详细说明不将其设为常量。

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


解决方案

运行时代码中的C++对象模型通常被松散地处理。它有相当严格的规则,但有一堆后门要么被允许,要么被宣布为UB。后者意味着您仍然可以编写代码来执行该操作,但C++不能保证该代码的行为。

在常量计算中(也称为代码的编译时执行),不是情况。constexpr上的限制专门用于允许对象模型成为您必须遵循的真实对象,没有可行的后门。即使是它偶尔允许的那些代码,也被明确要求是格式错误的并产生编译错误,而不是静默UB。

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

memcpy处理字节存储,来回复制它们,而不知道它们是什么意思。bit_cast知道源对象和目标对象,除非源对象和目标对象适合bit_cast操作(即:普通可复制),否则不允许您这样做。

bit_cast在这两个对象的内容上也有very specific restrictions,如果您希望它在编译时工作的话。特别是,您不能bit_cast指针或包含任何类型的指针的任何对象。或引用。

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

相关文章