1#ifndef MSTL_CORE_CONTAINER_ARRAY_HPP__
2#define MSTL_CORE_CONTAINER_ARRAY_HPP__
8template <
bool IsConst,
size_t Size,
typename Array>
11 using container_type = Array;
12 using iterator = array_iterator<false, Size, container_type>;
13 using const_iterator = array_iterator<true, Size, container_type>;
16 using iterator_category = contiguous_iterator_tag;
17 using value_type =
typename container_type::value_type;
20 using difference_type =
typename container_type::difference_type;
21 using size_type =
typename container_type::size_type;
24 pointer ptr_ =
nullptr;
28 constexpr array_iterator() noexcept = default;
29 constexpr array_iterator(pointer ptr, const
size_t off = 0) noexcept
30 : ptr_(ptr), idx_(off) {}
32 MSTL_NODISCARD
constexpr reference operator *() const noexcept {
35 MSTL_NODISCARD
constexpr pointer operator ->() const noexcept {
36 MSTL_DEBUG_VERIFY(ptr_ && idx_ < Size,
"cannot dereference out of range array iterator");
40 constexpr array_iterator& operator ++() noexcept {
41 MSTL_DEBUG_VERIFY(ptr_ && idx_ < Size,
"cannot increment array iterator past end");
45 constexpr array_iterator operator ++(
int)
noexcept {
46 array_iterator tmp = *
this;
50 constexpr array_iterator& operator --() noexcept {
51 MSTL_DEBUG_VERIFY(ptr_ && idx_ != 0,
"cannot decrement array iterator before begin");
55 constexpr array_iterator operator --(
int)
noexcept {
56 array_iterator tmp = *
this;
61 constexpr array_iterator& operator +=(
const difference_type n)
noexcept {
62 idx_ +=
static_cast<size_t>(n);
65 constexpr array_iterator& operator -=(
const difference_type n)
noexcept {
69 MSTL_NODISCARD
constexpr difference_type operator -(
const array_iterator& rhs)
const noexcept {
70 return static_cast<difference_type
>(idx_ - rhs.idx_);
72 MSTL_NODISCARD
constexpr array_iterator operator -(
const difference_type n)
const noexcept {
73 array_iterator tmp = *
this;
77 MSTL_NODISCARD
constexpr array_iterator operator +(
const difference_type n)
const noexcept {
78 array_iterator tmp = *
this;
82 MSTL_NODISCARD
friend constexpr array_iterator operator +(
83 const difference_type n, array_iterator iter)
noexcept {
88 MSTL_NODISCARD
constexpr reference operator [](
const difference_type n)
const noexcept {
92 MSTL_NODISCARD
constexpr bool operator ==(
const array_iterator& rhs)
const noexcept {
93 return idx_ == rhs.idx_;
95 MSTL_NODISCARD
constexpr bool operator!=(
const array_iterator& rhs)
const noexcept {
96 return !(*
this == rhs);
98 MSTL_NODISCARD
constexpr bool operator <(
const array_iterator& rhs)
const noexcept {
99 return idx_ < rhs.idx_;
101 MSTL_NODISCARD
constexpr bool operator >(
const array_iterator& rhs)
const noexcept {
104 MSTL_NODISCARD
constexpr bool operator <=(
const array_iterator& rhs)
const noexcept {
105 return !(rhs < *
this);
107 MSTL_NODISCARD
constexpr bool operator >=(
const array_iterator& rhs)
const noexcept {
108 return !(*
this < rhs);
111 MSTL_NODISCARD
constexpr pointer base() const noexcept {
116template <
typename T,
size_t Size>
117class array :
public icollector<array<T, Size>> {
118 static_assert(is_object_v<T>,
"array only containers of object types.");
120 using base_type = icollector<array>;
124 using iterator = array_iterator<false, Size, array>;
125 using const_iterator = array_iterator<true, Size, array>;
126 using reverse_iterator =
_MSTL reverse_iterator<iterator>;
127 using const_reverse_iterator =
_MSTL reverse_iterator<const_iterator>;
133 constexpr array() noexcept = default;
134 MSTL_CONSTEXPR20 ~array() noexcept = default;
136 constexpr array(const array& rhs) noexcept = default;
137 constexpr array& operator =(const array& rhs) noexcept = default;
138 constexpr array(array&& rhs) noexcept = default;
139 constexpr array& operator =(array&& rhs) noexcept = default;
141 constexpr array(std::initializer_list<T> init) noexcept {
142 size_t size = init.
size() < Size ? init.size() : Size;
143 _MSTL copy(init.begin(), init.begin() + size, array_);
146 MSTL_NODISCARD
constexpr iterator begin() noexcept {
147 return iterator(array_, 0);
149 MSTL_NODISCARD
constexpr iterator end() noexcept {
150 return iterator(array_, Size);
152 MSTL_NODISCARD
constexpr const_iterator begin() const noexcept {
153 return const_iterator(array_, 0);
155 MSTL_NODISCARD
constexpr const_iterator end() const noexcept {
156 return const_iterator(array_, Size);
158 MSTL_NODISCARD
constexpr reverse_iterator rbegin() noexcept {
159 return reverse_iterator(end());
161 MSTL_NODISCARD
constexpr reverse_iterator rend() noexcept {
162 return reverse_iterator(begin());
164 MSTL_NODISCARD
constexpr const_reverse_iterator rbegin() const noexcept {
165 return const_reverse_iterator(end());
167 MSTL_NODISCARD
constexpr const_reverse_iterator rend() const noexcept {
168 return const_reverse_iterator(begin());
170 MSTL_NODISCARD
constexpr const_iterator cbegin() const noexcept {
171 return const_iterator(array_, 0);
173 MSTL_NODISCARD
constexpr const_iterator cend() const noexcept {
174 return const_iterator(array_, Size);
176 MSTL_NODISCARD
constexpr const_reverse_iterator crbegin() const noexcept {
177 return reverse_iterator(cend());
179 MSTL_NODISCARD
constexpr const_reverse_iterator crend() const noexcept {
180 return reverse_iterator(cbegin());
183 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
184 constexpr size_type
size() const noexcept {
187 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
188 constexpr size_type max_size() const noexcept {
191 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
192 constexpr bool empty() const noexcept {
196 MSTL_NODISCARD
constexpr reference at(size_type n) {
197 MSTL_DEBUG_VERIFY(n < Size,
"array subscript out of range");
200 MSTL_NODISCARD
constexpr const_reference at(size_type n)
const {
201 MSTL_DEBUG_VERIFY(n < Size,
"array subscript out of range");
204 MSTL_NODISCARD
constexpr reference operator[](size_type n)
noexcept {
205 MSTL_DEBUG_VERIFY(n < Size,
"array subscript out of range");
208 MSTL_NODISCARD
constexpr const_reference operator[](size_type n)
const noexcept {
209 MSTL_DEBUG_VERIFY(n < Size,
"array subscript out of range");
213 MSTL_NODISCARD
constexpr reference front() noexcept {
216 MSTL_NODISCARD
constexpr const_reference front() const noexcept {
219 MSTL_NODISCARD
constexpr reference back() noexcept {
220 return array_[Size - 1];
222 MSTL_NODISCARD
constexpr const_reference back() const noexcept {
223 return array_[Size - 1];
225 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
constexpr
229 MSTL_NODISCARD
constexpr const T* data() const noexcept {
233 constexpr void fill(
const T& value) {
237 constexpr void swap(array& x)
noexcept(is_nothrow_swappable_v<T>) {
241 MSTL_NODISCARD
constexpr bool operator ==(
const array& rhs)
const noexcept {
242 return _MSTL equal(this->cbegin(), this->cend(), rhs.cbegin());
244 MSTL_NODISCARD
constexpr bool operator <(
const array& rhs)
const noexcept {
249struct empty_array_element_tag {
250 constexpr explicit empty_array_element_tag() noexcept = default;
254class array<T, 0> : public icollector<array<T, 0>> {
255 static_assert(is_object_v<T>,
"array only containers of object types.");
257 using base_type = icollector<array>;
261 using iterator = array_iterator<false, 0, array>;
262 using const_iterator = array_iterator<true, 0, array>;
263 using reverse_iterator =
_MSTL reverse_iterator<iterator>;
264 using const_reverse_iterator =
_MSTL reverse_iterator<const_iterator>;
268 T, empty_array_element_tag> array_[1]{};
271 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
272 constexpr iterator
begin() noexcept {
275 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
276 constexpr iterator
end() noexcept {
279 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
280 constexpr const_iterator
begin() const noexcept {
281 return const_iterator{};
283 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
284 constexpr const_iterator
end() const noexcept {
285 return const_iterator{};
287 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
288 constexpr reverse_iterator
rbegin() noexcept {
289 return reverse_iterator(
end());
291 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
292 constexpr reverse_iterator
rend() noexcept {
293 return reverse_iterator(
begin());
295 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
296 constexpr const_reverse_iterator
rbegin() const noexcept {
297 return const_reverse_iterator(
end());
299 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
300 constexpr const_reverse_iterator
rend() const noexcept {
301 return const_reverse_iterator(
begin());
303 MSTL_NODISCARD MSTL_ALWAYS_INLINE
304 constexpr const_iterator
cbegin() const noexcept {
307 MSTL_NODISCARD MSTL_ALWAYS_INLINE
308 constexpr const_iterator
cend() const noexcept {
311 MSTL_NODISCARD MSTL_ALWAYS_INLINE
312 constexpr const_reverse_iterator
crbegin() const noexcept {
315 MSTL_NODISCARD MSTL_ALWAYS_INLINE
316 constexpr const_reverse_iterator
crend() const noexcept {
320 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
321 constexpr size_type
size() const noexcept {
324 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
325 constexpr size_type max_size() const noexcept {
328 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
329 constexpr bool empty() const noexcept {
333 MSTL_NODISCARD reference at(size_type) {
334 throw_exception(iterator_exception(
"array empty."));
338 MSTL_NODISCARD const_reference at(size_type)
const {
339 throw_exception(iterator_exception(
"array empty."));
343 MSTL_NODISCARD reference operator [](size_type)
noexcept {
344 throw_exception(iterator_exception(
"array index out of range"));
347 MSTL_NODISCARD const_reference operator [](size_type)
const noexcept {
348 throw_exception(iterator_exception(
"array index out of range"));
352 MSTL_NODISCARD reference front() noexcept {
353 throw_exception(iterator_exception(
"array empty."));
356 MSTL_NODISCARD const_reference front() const noexcept {
357 throw_exception(iterator_exception(
"array empty."));
361 MSTL_NODISCARD reference back() noexcept {
362 throw_exception(iterator_exception(
"array empty."));
366 MSTL_NODISCARD const_reference back() const noexcept {
367 throw_exception(iterator_exception(
"array empty."));
371 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
372 constexpr T*
data() noexcept {
375 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
376 constexpr const T*
data() const noexcept {
380 MSTL_ALWAYS_INLINE
constexpr void fill(
const T&) {}
381 MSTL_ALWAYS_INLINE
constexpr void swap(array&)
noexcept {}
383 MSTL_NODISCARD MSTL_ALWAYS_INLINE
constexpr bool operator ==(
const array&)
const noexcept {
return true; }
384 MSTL_NODISCARD MSTL_ALWAYS_INLINE
constexpr bool operator <(
const array&)
const noexcept {
return false; }
386#if MSTL_SUPPORT_DEDUCTION_GUIDES__
388template <
typename First,
typename... Rest>
390 static_assert(conjunction_v<is_same<First, Rest>...>,
"array types mismatch.");
395template <
typename First,
typename... Rest>
396array(First, Rest...) -> array<
typename _INNER __array_same<First, Rest...>::type, 1 +
sizeof...(Rest)>;
400template <
size_t Idx,
class T,
size_t Size>
401MSTL_NODISCARD
constexpr T&
get(array<T, Size>& arr)
noexcept {
402 static_assert(Idx < Size,
"array index out of bounds");
405template <
size_t Idx,
class T,
size_t Size>
406MSTL_NODISCARD
constexpr const T&
get(
const array<T, Size>& arr)
noexcept {
407 static_assert(Idx < Size,
"array index out of bounds");
410template <
size_t Idx,
class T,
size_t Size>
411MSTL_NODISCARD
constexpr T&&
get(array<T, Size>&& arr)
noexcept {
412 static_assert(Idx < Size,
"array index out of bounds");
415template <
size_t Idx,
class T,
size_t Size>
416MSTL_NODISCARD
constexpr const T&&
get(
const array<T, Size>&& arr)
noexcept {
417 static_assert(Idx < Size,
"array index out of bounds");
422template <
typename T,
size_t Size>
423struct tuple_size<array<T, Size>> : integral_constant<size_t, Size> { };
425template <
size_t Idx,
typename T,
size_t Size>
426struct tuple_element<Idx, array<T, Size>> {
427 static_assert(Idx < Size,
"array index is in range");
431template <
typename T,
size_t Size>
432MSTL_INLINE17
constexpr size_t tuple_size_v<array<T, Size>> = Size;
434template <
typename T,
size_t Size>
435MSTL_INLINE17
constexpr size_t tuple_size_v<const array<T, Size>> = Size;
MSTL_ALWAYS_INLINE enable_if_t< is_void_v< T >, future_result_t< T > > get(future< T > &f)
通用future结果获取函数
MSTL_NODISCARD constexpr bool equal(Iterator1 first1, Iterator1 last1, Iterator2 first2, BinaryPredicate binary_pred) noexcept(noexcept(++first1) &&noexcept(++first2) &&noexcept(binary_pred(*first1, *first2)))
比较两个范围是否相等
MSTL_NODISCARD constexpr bool lexicographical_compare(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, Compare comp) noexcept(noexcept(++first1) &&noexcept(++first2) &&noexcept(comp(*first1, *first2)) &&noexcept(first1==last1 &&first2 !=last2))
字典序比较两个范围
bool operator==(const function< Res(Args...)> &f, nullptr_t null) noexcept
等于空指针比较
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
MSTL_NODISCARD constexpr bool operator<(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
小于比较运算符
constexpr void fill(Iterator first, Iterator last, const T &value)
填充范围元素
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
constexpr Iterator2 copy(Iterator1 first, Iterator1 last, Iterator2 result)
复制范围元素
constexpr Iterator fill_n(Iterator first, size_t n, const T &value)
填充指定数量的元素
void swap()=delete
删除无参数的swap重载
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr bool empty(const Container &cont) noexcept(noexcept(cont.empty()))
检查容器是否为空
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) rend(Container &cont) noexcept(noexcept(cont.rend()))
获取const容器的反向起始迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) end(Container &cont) noexcept(noexcept(cont.end()))
获取容器的结束迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) size(const Container &cont) noexcept(noexcept(cont.size()))
获取容器的大小
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) data(Container &cont) noexcept(noexcept(cont.data()))
获取容器的底层数据指针
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) cend(const Container &cont) noexcept(noexcept(cont.cend()))
获取const容器的const结束迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) begin(Container &cont) noexcept(noexcept(cont.begin()))
获取容器的起始迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) crbegin(const Container &cont) noexcept(noexcept(cont.crbegin()))
获取const容器的const反向起始迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) cbegin(const Container &cont) noexcept(noexcept(cont.cbegin()))
获取const容器的const起始迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) rbegin(Container &cont) noexcept(noexcept(cont.rbegin()))
获取容器的反向起始迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) crend(const Container &cont) noexcept(noexcept(cont.crend()))
获取const容器的const反向结束迭代器
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名
MSTL_NODISCARD constexpr decltype(auto) size() const noexcept(noexcept(derived().size()))
获取集合大小
MSTL_NODISCARD constexpr bool empty() const noexcept(noexcept(derived().empty()))