8

C++ 标准库提供了多种“概念”,用于指定容器对象的接口。例如,std::vector实现ContainerSequenceRandomAccessContainerReversibleContainer概念。

是否有一个在 C++03 或 C++11 中指定的概念,它描述了一个Sequence保证元素之间连续内存的概念,以便:

static_cast<void*>(&some_sequence[N]) == static_cast<void*>(&some_sequence[0] + N)>

这将是一个有用的概念,因为它告诉您是否可以将 Container 与任何需要连续内存缓冲区的函数一起使用,例如std::istream::read.

我知道,在实践中,只有std::vector(并且我认为仅std::string在 C++11 中)实际上保证了一个底层的连续缓冲区——但这种保证是唯一的,std::vector还是有一个定义的“概念”来指示Sequence提供连续内存的泛型类?

4

3 回答 3

3

“连续容器”在 C++17 中指定。从$23.2.1/13 一般容器要求 [container.requirements.general]

连续容器是支持随机访问迭代器 ([random.access.iterators]) 并且其成员类型 iterator 和 const_iterator 是连续迭代器 ([iterator.requirements.general]) 的容器。

关于“连续迭代器”,24.2.1/5 美元一般来说 [iterator.requirements.general]

进一步满足以下要求的迭代器,即对于整数值 n 和可解引用的迭代器值 a 和 (a + n),*(a + n) 等价于 *(addressof(*a) + n),称为连续迭代器。

std::vector(除了std::vector<bool>)、std::arraystd::basic_string是连续容器。

于 2016-07-16T09:41:44.333 回答
2

我发现自己必须多次识别满足此功能的类型。我不知道发明这样一个特殊的“概念”是否优雅(想象它是一个涉及记忆的概念,这不是很抽象),但我同意这样的东西会很有用。

同时为了实用并将这个概念/要求转化为纯语法要求,让我们倒退。如果我们将自己限制在标准中,那么保证(或几乎保证)连续性的类是什么?按相关性排序:

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[0]*t.data()

2) 在 . 上使用某种 SFINAE .data()

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]and std::initializer_list<T>。所以,你可以用....data()上面的std::data(...)代替。

结论,我认为这是一个很好的约定,如果一个类型有一个data函数(或.data()在 C++11 中)返回一个指向值类型的指针,那么元素是连续的。

(好吧,那怎么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

于 2016-07-16T06:18:59.573 回答
0

从 C++03 开始​​,仅std::vector保证 (23.2.4.1):

向量的元素是连续存储的,这意味着如果 v 是一个向量,其中 T 是除 bool 之外的某种类型,那么对于所有 0 <= n < v,它都遵循恒等式 &v[n] == &v[0] + n 。尺寸()​​。

C++11 添加了 std::array,它是固定大小数组的包装器,并且也具有相同的属性。我认为没有办法知道任何容器是否具有这样的属性。

于 2013-03-19T20:59:15.603 回答