我发现自己必须多次识别满足此功能的类型。我不知道发明这样一个特殊的“概念”是否优雅(想象它是一个涉及记忆的概念,这不是很抽象),但我同意这样的东西会很有用。
同时为了实用并将这个概念/要求转化为纯语法要求,让我们倒退。如果我们将自己限制在标准中,那么保证(或几乎保证)连续性的类是什么?按相关性排序:
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