【问题标题】:Why is there no std::data() overload for std::valarray?为什么 std::valarray 没有 std::data() 重载?
【发布时间】:2021-05-10 08:10:09
【问题描述】:

C++11 引入了std::begin(std::valarray&)std::end(std::valarray&)

C++17 引入了std::data(),它适用于std::vectorstd::array、C 样式数组等。但是为什么没有为std::valarray 引入重载的std::data()

std::valarray被指定为连续存储,可以通过a[0]的地址访问(见Notes)。

std::data(std::valarray& a) 可以简单地定义为返回 &(a[0])。为什么没有做到这一点?是疏忽吗?

我的动机是我正在开发一个通用的序列化库。当它从源(例如 CBOR)接收到连续的二进制数数组时,它会检测目标容器是否具有重载的 data(container) 函数、container.resize(n) 成员函数以及适当的 value_type(匹配原始数字类型)。这三者的存在使得将源数据直接有效地memcpy() 直接放入目标容器成为可能。如果std::data(std::valarray&) 过载,我的生活会更简单。缺少它并不是什么大问题,但它确实使代码更加混乱。


ADDENDUM:我之所以要检测data 函数是因为它告诉我目标容器是连续的。如果它是连续的,那么我可以进行有效的字节复制(通过std::memcpystd::copy 并不重要)。如果它不连续,那么我必须一次解压每个未对齐的源数组第一个,然后根据容器类型使用push_backemplace 等将其附加到目标容器。


附录 2:我决定使用适配器和特征方法,而不是检测 data 函数的存在。这将使支持非标准或用户定义的容器类型变得更加容易。我关于为什么没有std::data(std::valarray& a) 的问题仍然存在。


附录 3:我应该澄清一下,我需要为 CBOR 类型的数组做这个骇客,它只能是数字。此外,源缓冲区中的数字未与元素边界对齐。我知道二进制数据可能需要字节序交换,如果不小心处理,将字节复制到浮点类型可能会触发奇怪的 NaN 行为。

我现在后悔提到我的动机,应该让std::data(std::valarray& a) 问题独立存在。这个问题已经变成了什么样的火车残骸,哈哈。 :-)

【问题讨论】:

  • "两者的存在使得可以有效地将memcpy() 源数据直接放入目标容器中" - 你不使用std::copy() 是有原因的吗? /std::copy_n() 为此目的,让编译器在可能的情况下将其优化为memcpy?您无需访问每个容器 data() 即可使用 std::copy/_n,只需使用迭代器即可。
  • 我认为 std::valarray 并不真正被视为 STL 的一部分,因为它不符合 STL 的理念。
  • @remy 采用非 4 字节对齐的 32 位 int 数据缓冲区。将这些字节 memcpy 到 32 字节整数的缓冲区是合法的,但形成指向未对齐缓冲区的 int 指针并 std 复制它们是不合法的。 OTOH,将 unswizzled 的错误字节序 IEEE 字节放入浮点数可能会导致硬陷阱值。
  • @Galik 基于 STL 的常用用法存在一些混淆。 What's the difference between “STL” and “C++ Standard Library”?
  • 原提案N4017中没有提到valarrays。

标签: c++ memcpy c++-standard-library contiguous valarray


【解决方案1】:

正如 cmets 中的 1201ProgramAlarm 所述,the proposal to add std::data 没有提及 std::valarray。除非有人能指出为什么&(a[0]) 不能用于获取valarray 的数据指针,否则简单的答案是valarray 在提案中被遗忘或忽略。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-17
    • 2019-10-06
    • 1970-01-01
    • 2022-10-02
    • 2011-05-05
    • 1970-01-01
    • 2020-10-28
    相关资源
    最近更新 更多