C ++连续序列概念
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.requirements.general])。
关于“连续迭代器”,$ 24.2.1 / 5一般[iterator.requirements.general]:
迭代器进一步满足要求,对于整数值n和可解引用的迭代器值a和(a + n),*(a + n)等价于*(addressof(* 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]
,则*t.data()
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):
一个向量的元素是连续存储的,这意味着如果v是一个向量,其中T是除bool以外的某种类型,那么它对所有0 <= n <v都服从身份&v [n] ==&v [0] + n 。尺寸()。
C ++ 11增加了std :: array,它是固定大小数组的封装,并且也具有相同的属性。 我不认为有任何方法可以知道任何集装箱是否拥有此类财产。
链接地址: http://www.djcxy.com/p/69775.html上一篇: C++ Contiguous Sequence Concept
下一篇: Bitmap compressed with quality=100 bigger file size than original