MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
memory_view.hpp
1#ifndef MSTL_CORE_MEMORY_MEMORY_VIEW_HPP__
2#define MSTL_CORE_MEMORY_MEMORY_VIEW_HPP__
3#include "../container/array.hpp"
9
10MSTL_INLINE17 constexpr size_t dynamic_extent = numeric_traits<size_t>::max();
11
12
14template <size_t Extent>
15struct extent_storage {
16 constexpr extent_storage(size_t) noexcept {}
17 static constexpr size_t extent() noexcept { return Extent; }
18};
19template <>
20struct extent_storage<dynamic_extent> {
21private:
22 size_t extent_value_;
23public:
24 constexpr extent_storage(const size_t extent_value) noexcept : extent_value_(extent_value) {}
25 constexpr size_t extent() const noexcept { return extent_value_; }
26};
28
29
30template <typename Element, size_t Extent = dynamic_extent>
31class memory_view {
32public:
33 using element_type = Element;
34
35 using value_type = remove_cv_t<Element>;
36 using size_type = size_t;
37 using difference_type = ptrdiff_t;
38 using pointer = Element*;
39 using const_pointer = const Element*;
40 using reference = element_type&;
41 using const_reference = const element_type&;
42
43 using iterator = normal_iterator<pointer>;
44 using reverse_iterator = _MSTL reverse_iterator<iterator>;
45
46private:
47 template <typename U, size_t ArrayExtent, enable_if_t<
48 Extent == dynamic_extent || ArrayExtent == Extent, int> = 0>
49 using is_compatible_array = is_array_convertible<Element, U>;
50
51 template <typename Ref>
53
54 compressed_pair<_INNER extent_storage<Extent>, pointer> extent_pair_;
55
56
57 template <size_t, size_t Count, enable_if_t<
58 Count != dynamic_extent, int> = 0>
59 static constexpr size_t subspan_extent() noexcept {
60 return Count;
61 }
62
63 template <size_t Offset, size_t Count, enable_if_t<
64 Count == dynamic_extent && Extent != dynamic_extent, int> = 0>
65 static constexpr size_t subspan_extent() noexcept {
66 return Extent - Offset;
67 }
68
69 template <size_t, size_t Count, enable_if_t<
70 Count == dynamic_extent && Extent == dynamic_extent, int> =0>
71 static constexpr size_t subspan_extent() noexcept{
72 return dynamic_extent;
73 }
74
75 template <size_t UE = Extent, enable_if_t<UE != dynamic_extent, int> = 0>
76 static MSTL_ALWAYS_INLINE constexpr void check_extend(const size_t count) noexcept {
77 MSTL_CONSTEXPR_ASSERT(count == Extent);
78 }
79 template <size_t UE = Extent, enable_if_t<UE == dynamic_extent, int> = 0>
80 static MSTL_ALWAYS_INLINE constexpr void check_extend(const size_t) noexcept {}
81
82 template <size_t UE = Extent, enable_if_t<UE != dynamic_extent, int> = 0>
83 MSTL_ALWAYS_INLINE constexpr void check_count(const size_t Count) const noexcept {
84 static_assert(Count <= Extent, "COunt must less than Extend");
85 }
86 template <size_t UE = Extent, enable_if_t<UE == dynamic_extent, int> = 0>
87 MSTL_ALWAYS_INLINE constexpr void check_count(const size_t Count) const noexcept {
88 MSTL_CONSTEXPR_ASSERT(Count <= size())
89 }
90
91 template <size_t Offset, size_t Count, enable_if_t<Count == dynamic_extent, int> = 0>
92 constexpr decltype(auto) subspan_aux() const noexcept {
93 using view = memory_view<element_type, subspan_extent<Offset, Count>()>;
94 return view{data() + Offset, size() - Offset};
95 }
96 template <size_t Offset, size_t Count, enable_if_t<Count != dynamic_extent, int> = 0>
97 constexpr decltype(auto) subspan_aux() const noexcept {
98 using view = memory_view<element_type, subspan_extent<Offset, Count>()>;
99 memory_view::check_count<Extent>(Count);
100 memory_view::check_count<Extent>(Count + Offset);
101 return view{data() + Offset, Count};
102 }
103
104public:
105 constexpr memory_view() noexcept
106#ifdef MSTL_STANDARD_20__
107 requires ((Extent + 1u) <= 1u)
108#endif
109 : extent_pair_(exact_arg_construct_tag{}, 0, nullptr) {}
110
111#ifdef MSTL_STANDARD_20__
112 template <contiguous_iterator Iter>
113 requires is_compatible_ref<iter_reference_t<Iter>>::value
114#else
115 template <typename Iter, enable_if_t<is_cot_iter_v<Iter>, int> = 0>
116#endif
117 constexpr
118#ifdef MSTL_STANDARD_20__
119 explicit(Extent != dynamic_extent)
120#endif
121 memory_view(Iter first, size_type count) noexcept
122 : extent_pair_(exact_arg_construct_tag{}, count, _MSTL to_address(first)) {
123 memory_view::check_extend<Extent>(count);
124 }
125
126#ifdef MSTL_STANDARD_20__
127 template <contiguous_iterator Iter, sized_sentinel_for<Iter> End>
128 requires is_compatible_ref<iter_reference_t<Iter>>::value && (!is_convertible_v<End, size_type>)
129#else
130 template <typename Iter, typename End, enable_if_t<is_cot_iter_v<Iter>, int> = 0>
131#endif
132 constexpr
134 explicit(Extent != dynamic_extent)
135#endif
136 memory_view(Iter first, End last) noexcept(noexcept(last - first))
137 : extent_pair_(exact_arg_construct_tag{}, static_cast<size_type>(last - first), _MSTL to_address(first)) {
138 memory_view::check_extend<Extent>(last - first);
139 }
140
141 template <size_t AE>
142#ifdef MSTL_STANDARD_20__
143 requires (Extent == dynamic_extent || AE == Extent)
144#endif
145 constexpr memory_view(type_identity_t<element_type> (&arr)[AE]) noexcept
146 : memory_view(static_cast<pointer>(arr), AE) {}
147
148 template <typename U, size_t AE>
149#ifdef MSTL_STANDARD_20__
150 requires is_compatible_array<U, AE>::value
151#endif
152 constexpr memory_view(array<U, AE>& arr) noexcept
153 : memory_view(static_cast<pointer>(arr.data()), AE) {}
154
155 template <typename U, size_t AE>
156#ifdef MSTL_STANDARD_20__
157 requires is_compatible_array<const U, AE>::value
158#endif
159 constexpr memory_view(const array<U, AE>& arr) noexcept
160 : memory_view(static_cast<pointer>(arr.data()), AE) {}
161
162 constexpr memory_view(const memory_view&) noexcept = default;
163
164 template <typename U, size_t OE>
165#ifdef MSTL_STANDARD_20__
166 requires (Extent == dynamic_extent || OE == dynamic_extent || Extent == OE)
167 && is_array_convertible_v<Element, U>
168#endif
169 constexpr
171 explicit(Extent != dynamic_extent && OE == dynamic_extent)
172#endif
173 memory_view(const memory_view<U, OE>& other) noexcept
174 : extent_pair_(other.extent_pair_) {
175 memory_view::check_extend<Extent>(other.size());
176 }
177
178 constexpr memory_view& operator =(const memory_view&) noexcept = default;
179
180 MSTL_CONSTEXPR20 ~memory_view() noexcept = default;
181
182
183 MSTL_NODISCARD constexpr size_type size() const noexcept {
184 return extent_pair_.get_base().extent();
185 }
186
187 MSTL_NODISCARD constexpr size_type size_bytes() const noexcept {
188 return size() * sizeof(element_type);
189 }
190
191 MSTL_NODISCARD constexpr bool empty() const noexcept {
192 return size() == 0;
193 }
194
195
196 MSTL_NODISCARD constexpr reference front() const noexcept {
197 MSTL_CONSTEXPR_ASSERT(!empty());
198 return *extent_pair_.value;
199 }
200
201 MSTL_NODISCARD constexpr reference back() const noexcept {
202 MSTL_CONSTEXPR_ASSERT(!empty());
203 return *(extent_pair_.value + (size() - 1));
204 }
205
206 MSTL_NODISCARD constexpr reference operator [](size_type index) const noexcept {
207 MSTL_CONSTEXPR_ASSERT(index < size());
208 return *(extent_pair_.value + index);
209 }
210
211 MSTL_NODISCARD constexpr pointer data() const noexcept {
212 return extent_pair_.value;
213 }
214
215 MSTL_NODISCARD constexpr iterator begin() const noexcept {
216 return iterator(extent_pair_.value);
217 }
218 MSTL_NODISCARD constexpr iterator end() const noexcept {
219 return iterator(extent_pair_.value + size());
220 }
221
222 MSTL_NODISCARD constexpr reverse_iterator rbegin() const noexcept {
223 return reverse_iterator(end());
224 }
225 MSTL_NODISCARD constexpr reverse_iterator rend() const noexcept {
226 return reverse_iterator(begin());
227 }
228
229 template <size_t Count>
230 constexpr memory_view<element_type, Count> first() const noexcept {
231 memory_view::check_count<Extent>(Count);
232 using view = memory_view<element_type, Count>;
233 return view{ data(), Count };
234 }
235
236 constexpr memory_view<element_type>
237 first(size_type count) const noexcept {
238 MSTL_CONSTEXPR_ASSERT(count <= size());
239 return { data(), count };
240 }
241
242 template <size_t Count>
243 constexpr memory_view<element_type, Count> last() const noexcept {
244 memory_view::check_count<Extent>(Count);
245 using view = memory_view<element_type, Count>;
246 return view{ data() + (size() - Count), Count };
247 }
248
249 constexpr memory_view<element_type>
250 last(size_type count) const noexcept {
251 MSTL_CONSTEXPR_ASSERT(count <= size());
252 return { data() + (size() - count), count };
253 }
254
255 template <size_t Offset, size_t Count = dynamic_extent>
256 constexpr auto subspan() const noexcept
257 -> memory_view<element_type, subspan_extent<Offset, Count>()> {
258 memory_view::check_count<Extent>(Offset);
259 return this->template subspan_aux<Offset, Count>();
260 }
261
262 constexpr memory_view<element_type>
263 subspan(size_type offset, size_type count = dynamic_extent) const noexcept {
264 MSTL_CONSTEXPR_ASSERT(offset <= size());
265 if (count == dynamic_extent)
266 count = size() - offset;
267 else {
268 MSTL_CONSTEXPR_ASSERT(count <= size());
269 MSTL_CONSTEXPR_ASSERT(offset + count <= size());
270 }
271 return {data() + offset, count};
272 }
273};
274
275#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
276template <typename T, size_t ArrayExtent>
277memory_view(T(&)[ArrayExtent]) -> memory_view<T, ArrayExtent>;
278
279template <typename T, size_t ArrayExtent>
280memory_view(array<T, ArrayExtent>&) -> memory_view<T, ArrayExtent>;
281
282template <typename T, size_t ArrayExtent>
283memory_view(const array<T, ArrayExtent>&) -> memory_view<const T, ArrayExtent>;
284
285#ifdef MSTL_STANDARD_20__
286template <contiguous_iterator Iter, typename End>
287#else
288template <typename Iter, typename End>
289#endif
290memory_view(Iter, End) -> memory_view<remove_reference_t<iter_reference_t<Iter>>>;
291#endif
292
293template <typename T, size_t Extent = dynamic_extent>
294using span = memory_view<T, Extent>;
295
296
297template <typename T, size_t Extent>
298memory_view<const byte_t, Extent == dynamic_extent ? dynamic_extent : Extent * sizeof(T)>
299as_bytes(memory_view<T, Extent> sp) noexcept {
300 auto data_ptr = reinterpret_cast<const byte_t*>(sp.data());
301 auto size_bytes = sp.size_bytes();
302 constexpr auto extent = Extent == dynamic_extent ? dynamic_extent : Extent * sizeof(T);
303 return memory_view<const byte_t, extent>{data_ptr, size_bytes};
304}
305
306template <typename T, size_t Extent, typename = enable_if_t<!is_const_v<T>>>
307memory_view<byte_t, Extent == dynamic_extent ? dynamic_extent : Extent * sizeof(T)>
308as_writable_bytes(memory_view<T, Extent> sp) noexcept {
309 auto data_ptr = reinterpret_cast<byte_t*>(sp.data());
310 auto size_bytes = sp.size_bytes();
311 constexpr auto extent = Extent == dynamic_extent ? dynamic_extent : Extent * sizeof(T);
312 return memory_view<byte_t, extent>{data_ptr, size_bytes};
313}
314
316
317#endif // MSTL_CORE_MEMORY_MEMORY_VIEW_HPP__
static MSTL_NODISCARD constexpr T max() noexcept
获取类型的最大值
MSTL压缩对实现
is_convertible< FromElement(*)[], ToElement(*)[]> is_array_convertible
判断数组元素类型FromElement是否可以转换为ToElement
unsigned char byte_t
字节类型,定义为无符号字符
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
#define MSTL_STANDARD_20__
使用C++20或更高标准编译
MSTL_INLINE17 constexpr bool is_cot_iter_v
检查是否为连续迭代器
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
uint64_t size_t
无符号大小类型
int64_t ptrdiff_t
指针差类型
constexpr T * to_address(T *ptr) noexcept
安全地获取原始指针指向的地址
typename remove_cv< T >::type remove_cv_t
remove_cv的便捷别名
typename type_identity< T >::type type_identity_t
type_identity的便捷别名
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
MSTL标准迭代器适配器
MSTL数值特征
MSTL反向迭代器
查询数组指定维度的大小