c++连续序列概念
C++ Contiguous Sequence Concept
c++标准库提供了各种"概念",用于指定容器对象的接口。例如,std::vector
实现了Container
、Sequence
、RandomAccessContainer
、ReversibleContainer
的概念。
是否有一个概念,在c++ 03或c++ 11中指定,描述一个Sequence
来保证元素之间的连续内存,以便:
static_cast<void*>(&some_sequence[N]) == static_cast<void*>(&some_sequence[0] + N)>
这将是一个有用的概念,因为它告诉您是否可以将容器用于任何需要连续内存缓冲区的函数,例如std::istream::read
。
我知道,在实践中,只有std::vector
(我认为std::string
在c++ 11中只有)实际上保证了一个底层的连续缓冲区-但是这个保证是std::vector
独有的,还是有一个定义的"概念",表明一个通用的Sequence
类提供连续内存?
"连续容器"在c++ 17中被指定。从$23.2.1/13起一般集装箱要求[container.requirements. General]:
连续容器是支持随机访问迭代器([random.access.iterators])的容器,其成员类型iterator和const_iterator都是连续迭代器([iterator.require .general])。
关于"连续迭代器",一般$24.2.1/5[iterator.requirements.general]:
进一步满足以下要求的迭代器称为连续迭代器:对于整型值n和可解引用迭代器值a和(a + n), *(a + n)等于*(addressoft (*a) + n)。
std::vector (std::vector<bool>
除外)、std::array和std::basic_string是连续的容器。
我发现自己不得不多次识别满足此特性的类型。我不知道发明这样一个特殊的"概念"是否优雅(想象它是一个涉及记忆的概念,这不是很抽象),但我同意这样的东西将是有用的。
同时,为了实用,把这个概念/需求转换成一个纯语法需求,让我们往回走。如果我们将自己限制在标准中,那么保证(或几乎保证)连续性的类是什么?按相关顺序:std::vector<T>
T[N] // !!
std::array<T, N>
std::string
std::initializer_list<T>
std::valarray<T>
其中std::vector
、std::array
、std::string
有一个成员函数.data()
。因此,如果这对您来说足够了,可以依赖成员.data() -> T*
的存在来表示连续内存。
你有两个选择:
1)让努力使用成员函数.data()
来引发语法错误,如果类型不是连续的。(如果你用*t.data()
代替t[0]
也不难)
2)在.data()
上使用某种SFINAE。
template<class ContiguousSequence, typename = decltype(std::declval<ContigiousSequence>().data())>
void fun(ContiguousSequence&& s){...} // this function will only work with contiguous data
此外,c++ 17有std::data
,它将.data()
泛化到所有类型,并为T[N]
和std::initializer_list<T>
附加了重载。所以,你可以用上面的std::data(...)
代替....data()
。
结论,我认为这是一个很好的惯例是如果一个类型有一个
data
函数(或c++ 11中的.data()
函数),该函数返回一个指向该值类型的指针,则该元素是连续的。
(好的,std::valarray<T>
呢?它不起作用,除非你重载std::data(std::valarray<T>&)
。但是谁会使用std::valarray
呢?我认为这是c++中一个被遗弃的角落)
最后,请注意,例如,明显的std::map
和不太明显的std::deque
没有.data()
(或std::data(...)
)函数。boost::multi_array<..., N>
有一个.data()
成员,并返回一个指向数组元素的指针,它不清楚这是否是你想要的连续序列(因为顺序不明显),但在某种意义上它也是一个连续的内存分配。
目前有两个建议解决这个问题(但是在迭代器级别)http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3884.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4284.html
从c++ 03开始,只有std::vector
保证(23.2.4.1):
vector的元素是存储的连续的,意思是如果v是a向量,其中T是输入bool以外的类型,则服从v[n] == &v[0] + n for所有0 <= n
虽然这个问题是专门针对c++ 11提出的,但我觉得至少值得注意的是,c++ 20为此引入了一个名为
std::ranges::contiguous_range
的适用概念,因为容器基本上是一个范围。例如:#include <list> #include <ranges> #include <vector> static_assert(not std::ranges::contiguous_range<std::list<int>>); static_assert(std::ranges::contiguous_range<std::vector<int>>);
- 模板元程序查找相似的连续类型名称
- EASTL矢量<向量<int>>连续的
- 当需要超过16GB的连续内存时,内存分配失败
- 我应该如何表示我拥有的连续元素序列?
- 蛇在C++不会连续转两次
- 有没有一种优雅而快速的方法来测试整数中的 1 位是否位于连续区域
- 如何知道n!是否可以表示为三个连续数字的乘法?
- 连续枚举 C++11
- 两个连续的 OpenMP 并行区域会相互减慢速度
- 可以将两个相同类型的连续数组视为一个数组吗?
- C++,您能否设计一种数据结构,将指针保存在连续内存中并且不会使它们失效?
- 我已经建立了递归关系,它找到了两个字符串之间最长的连续公共字符串,我怎么能跳过其中一个字符串中的一个字符
- 这种用于查找连续子数组中最大和的递归算法有什么优势吗?
- std::stack 是连续的吗?
- 检查连续对的字符串C++
- 如何使用 fprintf 将连续的 512 字节保存到文件中
- 使用连续字符及其路径查找矩阵中最长路径的长度
- 是否确保 2 个连续的 std::chrono::steady_clock::now() 不相等?
- 向量的内存位置不连续
- 查找给定范围内最长连续 1 的频率