MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
array.hpp
1#ifndef MSTL_CORE_CONTAINER_ARRAY_HPP__
2#define MSTL_CORE_CONTAINER_ARRAY_HPP__
7
8template <bool IsConst, size_t Size, typename Array>
9struct array_iterator {
10private:
11 using container_type = Array;
12 using iterator = array_iterator<false, Size, container_type>;
13 using const_iterator = array_iterator<true, Size, container_type>;
14
15public:
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;
22
23private:
24 pointer ptr_ = nullptr;
25 size_t idx_ = 0;
26
27public:
28 constexpr array_iterator() noexcept = default;
29 constexpr array_iterator(pointer ptr, const size_t off = 0) noexcept
30 : ptr_(ptr), idx_(off) {}
31
32 MSTL_NODISCARD constexpr reference operator *() const noexcept {
33 return *operator->();
34 }
35 MSTL_NODISCARD constexpr pointer operator ->() const noexcept {
36 MSTL_DEBUG_VERIFY(ptr_ && idx_ < Size, "cannot dereference out of range array iterator");
37 return ptr_ + idx_;
38 }
39
40 constexpr array_iterator& operator ++() noexcept {
41 MSTL_DEBUG_VERIFY(ptr_ && idx_ < Size, "cannot increment array iterator past end");
42 ++idx_;
43 return *this;
44 }
45 constexpr array_iterator operator ++(int) noexcept {
46 array_iterator tmp = *this;
47 ++*this;
48 return tmp;
49 }
50 constexpr array_iterator& operator --() noexcept {
51 MSTL_DEBUG_VERIFY(ptr_ && idx_ != 0, "cannot decrement array iterator before begin");
52 --idx_;
53 return *this;
54 }
55 constexpr array_iterator operator --(int) noexcept {
56 array_iterator tmp = *this;
57 --*this;
58 return tmp;
59 }
60
61 constexpr array_iterator& operator +=(const difference_type n) noexcept {
62 idx_ += static_cast<size_t>(n);
63 return *this;
64 }
65 constexpr array_iterator& operator -=(const difference_type n) noexcept {
66 return *this += -n;
67 }
68
69 MSTL_NODISCARD constexpr difference_type operator -(const array_iterator& rhs) const noexcept {
70 return static_cast<difference_type>(idx_ - rhs.idx_);
71 }
72 MSTL_NODISCARD constexpr array_iterator operator -(const difference_type n) const noexcept {
73 array_iterator tmp = *this;
74 tmp -= n;
75 return tmp;
76 }
77 MSTL_NODISCARD constexpr array_iterator operator +(const difference_type n) const noexcept {
78 array_iterator tmp = *this;
79 tmp += n;
80 return tmp;
81 }
82 MSTL_NODISCARD friend constexpr array_iterator operator +(
83 const difference_type n, array_iterator iter) noexcept {
84 iter += n;
85 return iter;
86 }
87
88 MSTL_NODISCARD constexpr reference operator [](const difference_type n) const noexcept {
89 return *(*this + n);
90 }
91
92 MSTL_NODISCARD constexpr bool operator ==(const array_iterator& rhs) const noexcept {
93 return idx_ == rhs.idx_;
94 }
95 MSTL_NODISCARD constexpr bool operator!=(const array_iterator& rhs) const noexcept {
96 return !(*this == rhs);
97 }
98 MSTL_NODISCARD constexpr bool operator <(const array_iterator& rhs) const noexcept {
99 return idx_ < rhs.idx_;
100 }
101 MSTL_NODISCARD constexpr bool operator >(const array_iterator& rhs) const noexcept {
102 return rhs < *this;
103 }
104 MSTL_NODISCARD constexpr bool operator <=(const array_iterator& rhs) const noexcept {
105 return !(rhs < *this);
106 }
107 MSTL_NODISCARD constexpr bool operator >=(const array_iterator& rhs) const noexcept {
108 return !(*this < rhs);
109 }
110
111 MSTL_NODISCARD constexpr pointer base() const noexcept {
112 return ptr_;
113 }
114};
115
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.");
119
120 using base_type = icollector<array>;
121
122public:
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>;
128
129private:
130 T array_[Size];
131
132public:
133 constexpr array() noexcept = default;
134 MSTL_CONSTEXPR20 ~array() noexcept = default;
135
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;
140
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_);
144 }
145
146 MSTL_NODISCARD constexpr iterator begin() noexcept {
147 return iterator(array_, 0);
148 }
149 MSTL_NODISCARD constexpr iterator end() noexcept {
150 return iterator(array_, Size);
151 }
152 MSTL_NODISCARD constexpr const_iterator begin() const noexcept {
153 return const_iterator(array_, 0);
154 }
155 MSTL_NODISCARD constexpr const_iterator end() const noexcept {
156 return const_iterator(array_, Size);
157 }
158 MSTL_NODISCARD constexpr reverse_iterator rbegin() noexcept {
159 return reverse_iterator(end());
160 }
161 MSTL_NODISCARD constexpr reverse_iterator rend() noexcept {
162 return reverse_iterator(begin());
163 }
164 MSTL_NODISCARD constexpr const_reverse_iterator rbegin() const noexcept {
165 return const_reverse_iterator(end());
166 }
167 MSTL_NODISCARD constexpr const_reverse_iterator rend() const noexcept {
168 return const_reverse_iterator(begin());
169 }
170 MSTL_NODISCARD constexpr const_iterator cbegin() const noexcept {
171 return const_iterator(array_, 0);
172 }
173 MSTL_NODISCARD constexpr const_iterator cend() const noexcept {
174 return const_iterator(array_, Size);
175 }
176 MSTL_NODISCARD constexpr const_reverse_iterator crbegin() const noexcept {
177 return reverse_iterator(cend());
178 }
179 MSTL_NODISCARD constexpr const_reverse_iterator crend() const noexcept {
180 return reverse_iterator(cbegin());
181 }
182
183 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
184 constexpr size_type size() const noexcept {
185 return Size;
186 }
187 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
188 constexpr size_type max_size() const noexcept {
189 return Size;
190 }
191 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
192 constexpr bool empty() const noexcept {
193 return false;
194 }
195
196 MSTL_NODISCARD constexpr reference at(size_type n) {
197 MSTL_DEBUG_VERIFY(n < Size, "array subscript out of range");
198 return array_[n];
199 }
200 MSTL_NODISCARD constexpr const_reference at(size_type n) const {
201 MSTL_DEBUG_VERIFY(n < Size, "array subscript out of range");
202 return array_[n];
203 }
204 MSTL_NODISCARD constexpr reference operator[](size_type n) noexcept {
205 MSTL_DEBUG_VERIFY(n < Size, "array subscript out of range");
206 return array_[n];
207 }
208 MSTL_NODISCARD constexpr const_reference operator[](size_type n) const noexcept {
209 MSTL_DEBUG_VERIFY(n < Size, "array subscript out of range");
210 return array_[n];
211 }
212
213 MSTL_NODISCARD constexpr reference front() noexcept {
214 return array_[0];
215 }
216 MSTL_NODISCARD constexpr const_reference front() const noexcept {
217 return array_[0];
218 }
219 MSTL_NODISCARD constexpr reference back() noexcept {
220 return array_[Size - 1];
221 }
222 MSTL_NODISCARD constexpr const_reference back() const noexcept {
223 return array_[Size - 1];
224 }
225 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE constexpr
226 T* data() noexcept {
227 return array_;
228 }
229 MSTL_NODISCARD constexpr const T* data() const noexcept {
230 return array_;
231 }
232
233 constexpr void fill(const T& value) {
234 _MSTL fill_n(array_, Size, value);
235 }
236
237 constexpr void swap(array& x) noexcept(is_nothrow_swappable_v<T>) {
238 _MSTL swap(array_, x.array_);
239 }
240
241 MSTL_NODISCARD constexpr bool operator ==(const array& rhs) const noexcept {
242 return _MSTL equal(this->cbegin(), this->cend(), rhs.cbegin());
243 }
244 MSTL_NODISCARD constexpr bool operator <(const array& rhs) const noexcept {
245 return _MSTL lexicographical_compare(this->cbegin(), this->cend(), rhs.cbegin(), rhs.cend());
246 }
247};
248
249struct empty_array_element_tag {
250 constexpr explicit empty_array_element_tag() noexcept = default;
251};
252
253template <typename T>
254class array<T, 0> : public icollector<array<T, 0>> {
255 static_assert(is_object_v<T>, "array only containers of object types.");
256
257 using base_type = icollector<array>;
258
259public:
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>;
265
266private:
267 conditional_t<disjunction_v<is_default_constructible<T>, is_implicitly_default_constructible<T>>,
268 T, empty_array_element_tag> array_[1]{};
269
270public:
271 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
272 constexpr iterator begin() noexcept {
273 return iterator{};
274 }
275 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
276 constexpr iterator end() noexcept {
277 return iterator{};
278 }
279 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
280 constexpr const_iterator begin() const noexcept {
281 return const_iterator{};
282 }
283 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
284 constexpr const_iterator end() const noexcept {
285 return const_iterator{};
286 }
287 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
288 constexpr reverse_iterator rbegin() noexcept {
289 return reverse_iterator(end());
290 }
291 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
292 constexpr reverse_iterator rend() noexcept {
293 return reverse_iterator(begin());
294 }
295 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
296 constexpr const_reverse_iterator rbegin() const noexcept {
297 return const_reverse_iterator(end());
298 }
299 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
300 constexpr const_reverse_iterator rend() const noexcept {
301 return const_reverse_iterator(begin());
302 }
303 MSTL_NODISCARD MSTL_ALWAYS_INLINE
304 constexpr const_iterator cbegin() const noexcept {
305 return begin();
306 }
307 MSTL_NODISCARD MSTL_ALWAYS_INLINE
308 constexpr const_iterator cend() const noexcept {
309 return end();
310 }
311 MSTL_NODISCARD MSTL_ALWAYS_INLINE
312 constexpr const_reverse_iterator crbegin() const noexcept {
313 return rbegin();
314 }
315 MSTL_NODISCARD MSTL_ALWAYS_INLINE
316 constexpr const_reverse_iterator crend() const noexcept {
317 return rend();
318 }
319
320 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
321 constexpr size_type size() const noexcept {
322 return 0;
323 }
324 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
325 constexpr size_type max_size() const noexcept {
326 return 0;
327 }
328 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
329 constexpr bool empty() const noexcept {
330 return true;
331 }
332
333 MSTL_NODISCARD reference at(size_type) {
334 throw_exception(iterator_exception("array empty."));
335 return array_[0];
336 }
337
338 MSTL_NODISCARD const_reference at(size_type) const {
339 throw_exception(iterator_exception("array empty."));
340 return array_[0];
341 }
342
343 MSTL_NODISCARD reference operator [](size_type) noexcept {
344 throw_exception(iterator_exception("array index out of range"));
345 return *data();
346 }
347 MSTL_NODISCARD const_reference operator [](size_type) const noexcept {
348 throw_exception(iterator_exception("array index out of range"));
349 return *data();
350 }
351
352 MSTL_NODISCARD reference front() noexcept {
353 throw_exception(iterator_exception("array empty."));
354 return *data();
355 }
356 MSTL_NODISCARD const_reference front() const noexcept {
357 throw_exception(iterator_exception("array empty."));
358 return *data();
359 }
360
361 MSTL_NODISCARD reference back() noexcept {
362 throw_exception(iterator_exception("array empty."));
363 return *data();
364 }
365
366 MSTL_NODISCARD const_reference back() const noexcept {
367 throw_exception(iterator_exception("array empty."));
368 return *data();
369 }
370
371 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
372 constexpr T* data() noexcept {
373 return nullptr;
374 }
375 MSTL_NODISCARD MSTL_CONST_FUNCTION MSTL_ALWAYS_INLINE
376 constexpr const T* data() const noexcept {
377 return nullptr;
378 }
379
380 MSTL_ALWAYS_INLINE constexpr void fill(const T&) {}
381 MSTL_ALWAYS_INLINE constexpr void swap(array&) noexcept {}
382
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; }
385};
386#if MSTL_SUPPORT_DEDUCTION_GUIDES__
388template <typename First, typename... Rest>
389struct __array_same {
390 static_assert(conjunction_v<is_same<First, Rest>...>, "array types mismatch.");
391 using type = First;
392};
394
395template <typename First, typename... Rest>
396array(First, Rest...) -> array<typename _INNER __array_same<First, Rest...>::type, 1 + sizeof...(Rest)>;
397#endif // MSTL_SUPPORT_DEDUCTION_GUIDES__
398
399
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");
403 return arr[Idx];
404}
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");
408 return arr[Idx];
409}
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");
413 return _MSTL move(arr[Idx]);
414}
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");
418 return _MSTL move(arr[Idx]);
419}
420
421
422template <typename T, size_t Size>
423struct tuple_size<array<T, Size>> : integral_constant<size_t, Size> { };
424
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");
428 using type = T;
429};
430
431template <typename T, size_t Size>
432MSTL_INLINE17 constexpr size_t tuple_size_v<array<T, Size>> = Size;
433
434template <typename T, size_t Size>
435MSTL_INLINE17 constexpr size_t tuple_size_v<const array<T, Size>> = Size;
436
438#endif // MSTL_CORE_CONTAINER_ARRAY_HPP__
MSTL比较算法
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
小于比较运算符
#define MSTL_BUILD_TYPE_ALIAS(TYPE)
快速构建标准类型别名
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集合器接口
MSTL移位和修改算法
集合器接口模板
MSTL_NODISCARD constexpr decltype(auto) size() const noexcept(noexcept(derived().size()))
获取集合大小
MSTL_NODISCARD constexpr bool empty() const noexcept(noexcept(derived().empty()))