首页 > 解决方案 > 将非拥有位容器基于 std::vector 是个好主意吗? 标准::跨度?

问题描述

在我的几个项目中,我越来越需要处理内存中的连续位序列 - 高效(*)。到目前为止,我已经编写了一堆可内联的独立函数,以选择“位容器”类型(例如uint32_t)为模板,用于获取和设置位,将“或”和“与”应用于它们的值,定位容器,以位为单位的长度转换为以字节为单位的大小或容器中的长度等......看起来这是编写类的时间。

我知道 C++ 标准库有一个专门化的std::vector<bool>,这被许多人认为是一个设计缺陷——因为它的迭代器不暴露实际bool的 s,而是代理对象。无论这对于专业化来说是一个好主意还是一个坏主意,这绝对是我正在考虑的东西 - 一个显式的位代理类,希望它“总是”被优化掉(用constexpr,noexcept和很好地润滑inline)。因此,我正在考虑可能std::vector从标准库实现之一改编代码。

另一方面,我的预期课程:

从这个意义上说,它更像是位的跨度类。那么也许从跨度开始呢?我不知道,跨度仍然不标准;并且跨度中没有代理...

那么什么是我实现的良好基础(编辑:不是基类)?std::vector<bool>? std::span? 两个都?没有任何?或者 - 也许我正在重新发明轮子,这已经是一个已解决的问题?

笔记:

(*) - 到目前为止,SIMD 效率不高,但可能会在以后出现。此外,这可以在我们不 SIMDize 而是假装通道是正确线程的 CUDA 代码中使用。

标签: c++stdvectorclass-designc++20std-span

解决方案


而不是std::vector或者std::span我怀疑您的类的实现将与 共享更多共同点std::bitset,因为它几乎是相同的东西,除了(固定)运行时确定的大小。

事实上,您可能会采用典型的std::bitset实现并将<size_t N>模板参数作为size_t size_成员(或您喜欢的任何名称)移动到类中,并且您将拥有几乎没有任何更改的动态 bitset 类。你可能想摆脱任何你认为不重要的东西,比如构造函数std::string和朋友。

最后一步是删除底层数据的所有权:基本上,您将在构造函数中删除底层数组的创建,并使用一些指针维护现有数组的视图。

如果您的客户不同意用于存储的底层无符号整数类型(您称之为“位容器”),那么您可能还需要使您的类成为这种类型的模板,尽管如果每个人都同意会更简单说uint64_t

就目前std::vector<bool>而言,你不需要太多:vector你想做的一切,std::bitset可能也会做:vector增加的主要是动态增长——但你说过你不想要那个。vector<bool>具有代表单个位的代理对象概念,但std::bitset.

std::span您的基础数据的非所有权的想法,但我不认为这实际上代表了很多基础代码。如果这对您有用(主要是如果您有时使用编译时大小并且可以将某些std::span方法专门化为更多在这种情况下有效)。Extent == std::dynamic_extent


推荐阅读