1#ifndef MSTL_CORE_MEMORY_MEMORY_VIEW_HPP__
2#define MSTL_CORE_MEMORY_MEMORY_VIEW_HPP__
3#include "../container/array.hpp"
14template <
size_t Extent>
15struct extent_storage {
16 constexpr extent_storage(
size_t)
noexcept {}
17 static constexpr size_t extent() noexcept {
return Extent; }
20struct extent_storage<dynamic_extent> {
24 constexpr extent_storage(
const size_t extent_value) noexcept : extent_value_(extent_value) {}
25 constexpr size_t extent() const noexcept {
return extent_value_; }
30template <
typename Element,
size_t Extent = dynamic_extent>
33 using element_type = Element;
38 using pointer = Element*;
39 using const_pointer =
const Element*;
40 using reference = element_type&;
41 using const_reference =
const element_type&;
43 using iterator = normal_iterator<pointer>;
44 using reverse_iterator =
_MSTL reverse_iterator<iterator>;
47 template <
typename U,
size_t ArrayExtent,
enable_if_t<
48 Extent == dynamic_extent || ArrayExtent == Extent,
int> = 0>
51 template <
typename Ref>
54 compressed_pair<_INNER extent_storage<Extent>, pointer> extent_pair_;
58 Count != dynamic_extent,
int> = 0>
59 static constexpr size_t subspan_extent() noexcept {
64 Count == dynamic_extent && Extent != dynamic_extent,
int> = 0>
65 static constexpr size_t subspan_extent() noexcept {
66 return Extent - Offset;
70 Count == dynamic_extent && Extent == dynamic_extent,
int> =0>
71 static constexpr size_t subspan_extent() noexcept{
72 return dynamic_extent;
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);
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 {}
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");
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())
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};
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};
105 constexpr memory_view() noexcept
106#ifdef MSTL_STANDARD_20__
107 requires ((Extent + 1u) <= 1u)
109 : extent_pair_(exact_arg_construct_tag{}, 0, nullptr) {}
111#ifdef MSTL_STANDARD_20__
112 template <contiguous_iterator Iter>
113 requires is_compatible_ref<iter_reference_t<Iter>>::value
115 template <
typename Iter, enable_if_t<is_cot_iter_v<Iter>,
int> = 0>
118#ifdef MSTL_STANDARD_20__
119 explicit(Extent != dynamic_extent)
121 memory_view(Iter first, size_type
count) noexcept
123 memory_view::check_extend<Extent>(
count);
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>)
134 explicit(Extent != dynamic_extent)
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);
142#ifdef MSTL_STANDARD_20__
143 requires (Extent == dynamic_extent || AE == Extent)
146 : memory_view(
static_cast<pointer
>(arr), AE) {}
148 template <
typename U,
size_t AE>
149#ifdef MSTL_STANDARD_20__
150 requires is_compatible_array<U, AE>::value
152 constexpr memory_view(array<U, AE>& arr) noexcept
153 : memory_view(
static_cast<pointer
>(arr.data()), AE) {}
155 template <
typename U,
size_t AE>
156#ifdef MSTL_STANDARD_20__
157 requires is_compatible_array<const U, AE>::value
159 constexpr memory_view(
const array<U, AE>& arr) noexcept
160 : memory_view(
static_cast<pointer
>(arr.data()), AE) {}
162 constexpr memory_view(
const memory_view&)
noexcept =
default;
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>
171 explicit(Extent != dynamic_extent && OE == dynamic_extent)
173 memory_view(
const memory_view<U, OE>& other) noexcept
174 : extent_pair_(other.extent_pair_) {
175 memory_view::check_extend<Extent>(other.size());
178 constexpr memory_view& operator =(
const memory_view&)
noexcept =
default;
180 MSTL_CONSTEXPR20 ~memory_view() noexcept = default;
183 MSTL_NODISCARD constexpr size_type size() const noexcept {
184 return extent_pair_.get_base().extent();
187 MSTL_NODISCARD
constexpr size_type size_bytes() const noexcept {
188 return size() *
sizeof(element_type);
191 MSTL_NODISCARD
constexpr bool empty() const noexcept {
196 MSTL_NODISCARD
constexpr reference front() const noexcept {
197 MSTL_CONSTEXPR_ASSERT(!empty());
198 return *extent_pair_.value;
201 MSTL_NODISCARD
constexpr reference back() const noexcept {
202 MSTL_CONSTEXPR_ASSERT(!empty());
203 return *(extent_pair_.value + (size() - 1));
206 MSTL_NODISCARD
constexpr reference operator [](size_type index)
const noexcept {
207 MSTL_CONSTEXPR_ASSERT(index < size());
208 return *(extent_pair_.value + index);
211 MSTL_NODISCARD
constexpr pointer data() const noexcept {
212 return extent_pair_.value;
215 MSTL_NODISCARD
constexpr iterator begin() const noexcept {
216 return iterator(extent_pair_.value);
218 MSTL_NODISCARD
constexpr iterator end() const noexcept {
219 return iterator(extent_pair_.value + size());
222 MSTL_NODISCARD
constexpr reverse_iterator rbegin() const noexcept {
223 return reverse_iterator(end());
225 MSTL_NODISCARD
constexpr reverse_iterator rend() const noexcept {
226 return reverse_iterator(begin());
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 };
236 constexpr memory_view<element_type>
237 first(size_type
count)
const noexcept {
238 MSTL_CONSTEXPR_ASSERT(
count <= size());
239 return { data(),
count };
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 };
249 constexpr memory_view<element_type>
250 last(size_type
count)
const noexcept {
251 MSTL_CONSTEXPR_ASSERT(
count <= size());
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>();
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;
268 MSTL_CONSTEXPR_ASSERT(
count <= size());
269 MSTL_CONSTEXPR_ASSERT(offset +
count <= size());
271 return {data() + offset,
count};
275#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
276template <
typename T,
size_t ArrayExtent>
277memory_view(T(&)[ArrayExtent]) -> memory_view<T, ArrayExtent>;
279template <
typename T,
size_t ArrayExtent>
280memory_view(array<T, ArrayExtent>&) -> memory_view<T, ArrayExtent>;
282template <
typename T,
size_t ArrayExtent>
283memory_view(
const array<T, ArrayExtent>&) -> memory_view<const T, ArrayExtent>;
285#ifdef MSTL_STANDARD_20__
286template <contiguous_iterator Iter,
typename End>
288template <
typename Iter,
typename End>
290memory_view(Iter, End) -> memory_view<remove_reference_t<iter_reference_t<Iter>>>;
293template <
typename T,
size_t Extent = dynamic_extent>
294using span = memory_view<T, Extent>;
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};
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};
static MSTL_NODISCARD constexpr T max() noexcept
获取类型的最大值
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命名空间
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的便捷别名