33 using const_reference =
const T&;
35 using const_pointer =
const T*;
37 using difference_type = sarr_ext_detail::difference_type;
38 using size_type = sarr_ext_detail::size_type;
40 using iterator = pointer;
41 using const_iterator = const_pointer;
44 static constexpr size_t value_size =
sizeof(T);
45 static constexpr size_type extent = N;
46 static constexpr uint32_t allocated_bytes = view_policy::get_min_byte_size(0, N);
50 size_type m_cnt = size_type(0);
53 constexpr sarr_ext()
noexcept =
default;
57 core::call_dtor_n(data(), m_cnt);
60 constexpr sarr_ext(size_type count, const_reference value)
noexcept {
64 constexpr sarr_ext(size_type count)
noexcept {
68 template <
typename InputIt>
69 constexpr sarr_ext(InputIt first, InputIt last)
noexcept {
70 const auto count = (size_type)core::distance(first, last);
73 if constexpr (std::is_pointer_v<InputIt>) {
74 for (size_type i = 0; i < count; ++i)
75 operator[](i) = first[i];
76 }
else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
77 for (size_type i = 0; i < count; ++i)
78 operator[](i) = *(first[i]);
81 for (
auto it = first; it != last; ++it)
82 operator[](++i) = *it;
86 constexpr sarr_ext(std::initializer_list<T> il):
sarr_ext(il.begin(), il.end()) {}
91 GAIA_ASSERT(core::addressof(other) !=
this);
93 core::call_ctor_raw_n(data(), extent);
94 mem::move_elements<T, false>(m_data, other.m_data, other.size(), 0, extent, other.extent);
96 other.m_cnt = size_type(0);
99 sarr_ext& operator=(std::initializer_list<T> il) {
100 *
this =
sarr_ext(il.begin(), il.end());
105 GAIA_ASSERT(core::addressof(other) !=
this);
107 resize(other.size());
108 mem::copy_elements<T, false>(
109 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((
const uint8_t*)&other.m_data[0]), other.size(), 0, extent,
116 GAIA_ASSERT(core::addressof(other) !=
this);
119 mem::move_elements<T, false>(
120 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((uint8_t*)&other.m_data[0]), other.size(), 0, extent,
123 other.m_cnt = size_type(0);
128 GAIA_CLANG_WARNING_PUSH()
130 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
132 GAIA_NODISCARD
constexpr pointer data()
noexcept {
133 return GAIA_ACC((pointer)&m_data[0]);
136 GAIA_NODISCARD
constexpr const_pointer data()
const noexcept {
137 return GAIA_ACC((const_pointer)&m_data[0]);
140 GAIA_NODISCARD
constexpr decltype(
auto)
operator[](size_type pos)
noexcept {
141 GAIA_ASSERT(pos < size());
142 return view_policy::set({GAIA_ACC((
typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
145 GAIA_NODISCARD
constexpr decltype(
auto)
operator[](size_type pos)
const noexcept {
146 GAIA_ASSERT(pos < size());
147 return view_policy::get({GAIA_ACC((
typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
150 GAIA_CLANG_WARNING_POP()
152 constexpr void push_back(
const T& arg)
noexcept {
153 GAIA_ASSERT(size() < N);
155 auto* ptr = &data()[m_cnt++];
156 core::call_ctor(ptr, arg);
159 constexpr void push_back(T&& arg)
noexcept {
160 GAIA_ASSERT(size() < N);
162 auto* ptr = &data()[m_cnt++];
163 core::call_ctor(ptr, GAIA_MOV(arg));
166 template <
typename... Args>
167 constexpr decltype(
auto) emplace_back(Args&&... args)
noexcept {
168 GAIA_ASSERT(size() < N);
170 auto* ptr = &data()[m_cnt++];
171 core::call_ctor(ptr, GAIA_FWD(args)...);
172 return (reference)*ptr;
175 constexpr void pop_back()
noexcept {
176 GAIA_ASSERT(!empty());
178 auto* ptr = &data()[m_cnt - 1];
179 core::call_dtor(ptr);
187 iterator
insert(iterator pos,
const T& arg)
noexcept {
188 GAIA_ASSERT(size() < N);
189 GAIA_ASSERT(pos >= data());
190 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
192 const auto idxSrc = (size_type)core::distance(begin(), pos);
193 const auto idxDst = (size_type)core::distance(begin(), end());
195 mem::shift_elements_right<T, false>(m_data, idxDst, idxSrc, extent);
197 auto* ptr = &data()[idxSrc];
198 core::call_ctor(ptr, arg);
202 return iterator(&data()[idxSrc]);
208 iterator
insert(iterator pos, T&& arg)
noexcept {
209 GAIA_ASSERT(size() < N);
210 GAIA_ASSERT(pos >= data());
211 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
213 const auto idxSrc = (size_type)core::distance(begin(), pos);
214 const auto idxDst = (size_type)core::distance(begin(), end());
216 mem::shift_elements_right<T, false>(m_data, idxDst, idxSrc, extent);
218 auto* ptr = &data()[idxSrc];
219 core::call_ctor(ptr, GAIA_MOV(arg));
223 return iterator(&data()[idxSrc]);
228 constexpr iterator
erase(iterator pos)
noexcept {
229 GAIA_ASSERT(pos >= data());
230 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
235 const auto idxSrc = (size_type)core::distance(begin(), pos);
236 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
238 mem::shift_elements_left<T, false>(m_data, idxDst, idxSrc, extent);
240 auto* ptr = &data()[m_cnt - 1];
241 core::call_dtor(ptr);
245 return iterator(&data()[idxSrc]);
251 iterator
erase(iterator first, iterator last)
noexcept {
252 GAIA_ASSERT(first >= data())
253 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
254 GAIA_ASSERT(last > first);
255 GAIA_ASSERT(last <= (data() + size()));
260 const auto idxSrc = (size_type)core::distance(begin(), first);
261 const auto idxDst = size();
262 const auto cnt = (size_type)(last - first);
264 mem::shift_elements_left_fast<T, false>(m_data, idxDst, idxSrc, cnt, extent);
266 core::call_dtor_n(&data()[m_cnt - cnt], cnt);
270 return iterator(&data()[idxSrc]);
275 GAIA_ASSERT(pos < size());
277 const auto idxSrc = pos;
278 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
280 mem::shift_elements_left<T, false>(m_data, idxDst, idxSrc, extent);
282 auto* ptr = &data()[m_cnt - 1];
283 core::call_dtor(ptr);
287 return iterator(&data()[idxSrc]);
290 constexpr void clear() noexcept {
294 constexpr void resize(size_type count)
noexcept {
295 GAIA_ASSERT(count <= max_size());
298 if (count <= m_cnt) {
300 core::call_dtor_n(&data()[count], size() - count);
305 core::call_ctor_n(&data()[size()], count - size());
311 constexpr void resize(size_type count, const_reference value)
noexcept {
312 const auto oldCount = m_cnt;
315 if constexpr (std::is_copy_constructible_v<value_type>) {
316 const value_type valueCopy = value;
317 for (size_type i = oldCount; i < m_cnt; ++i)
318 operator[](i) = valueCopy;
320 for (size_type i = oldCount; i < m_cnt; ++i)
321 operator[](i) = value;
328 template <
typename Func>
330 size_type erased = 0;
331 size_type idxDst = 0;
332 size_type idxSrc = 0;
334 while (idxSrc < m_cnt) {
335 if (func(
operator[](idxSrc))) {
336 if (idxDst < idxSrc) {
337 auto* ptr = (uint8_t*)data();
338 mem::move_element<T, false>(ptr, ptr, idxDst, idxSrc, max_size(), max_size());
339 auto* ptr2 = &data()[idxSrc];
340 core::call_dtor(ptr2);
344 auto* ptr = &data()[idxSrc];
345 core::call_dtor(ptr);
356 GAIA_NODISCARD
constexpr size_type size() const noexcept {
360 GAIA_NODISCARD
constexpr bool empty() const noexcept {
364 GAIA_NODISCARD
constexpr size_type capacity() const noexcept {
368 GAIA_NODISCARD
constexpr size_type max_size() const noexcept {
372 GAIA_NODISCARD
constexpr decltype(
auto) front() noexcept {
373 GAIA_ASSERT(!empty());
374 return (reference)*begin();
377 GAIA_NODISCARD
constexpr decltype(
auto) front() const noexcept {
378 GAIA_ASSERT(!empty());
379 return (const_reference)*begin();
382 GAIA_NODISCARD
constexpr decltype(
auto) back() noexcept {
383 GAIA_ASSERT(!empty());
384 return (reference) operator[](m_cnt - 1);
387 GAIA_NODISCARD
constexpr decltype(
auto) back() const noexcept {
388 GAIA_ASSERT(!empty());
389 return (const_reference) operator[](m_cnt - 1);
392 GAIA_NODISCARD
constexpr auto begin() noexcept {
393 return iterator(data());
396 GAIA_NODISCARD
constexpr auto begin() const noexcept {
397 return const_iterator(data());
400 GAIA_NODISCARD
constexpr auto cbegin() const noexcept {
401 return const_iterator(data());
404 GAIA_NODISCARD
constexpr auto rbegin() noexcept {
405 return iterator((pointer)&back());
408 GAIA_NODISCARD
constexpr auto rbegin() const noexcept {
409 return const_iterator((pointer)&back());
412 GAIA_NODISCARD
constexpr auto crbegin() const noexcept {
413 return const_iterator((pointer)&back());
416 GAIA_NODISCARD
constexpr auto end() noexcept {
417 return iterator(GAIA_ACC((pointer)&m_data[0]) + size());
420 GAIA_NODISCARD
constexpr auto end() const noexcept {
421 return const_iterator(GAIA_ACC((const_pointer)&m_data[0]) + size());
424 GAIA_NODISCARD
constexpr auto cend() const noexcept {
425 return const_iterator(GAIA_ACC((const_pointer)&m_data[0]) + size());
428 GAIA_NODISCARD
constexpr auto rend() noexcept {
429 return iterator(GAIA_ACC((pointer)&m_data[0]) - 1);
432 GAIA_NODISCARD
constexpr auto rend() const noexcept {
433 return const_iterator(GAIA_ACC((const_pointer)&m_data[0]) - 1);
436 GAIA_NODISCARD
constexpr auto crend() const noexcept {
437 return const_iterator(GAIA_ACC((const_pointer)&m_data[0]) - 1);
440 GAIA_NODISCARD
constexpr bool operator==(
const sarr_ext& other)
const noexcept {
441 if (m_cnt != other.m_cnt)
443 const size_type n = size();
444 for (size_type i = 0; i < n; ++i)
445 if (!(
operator[](i) == other[i]))
450 GAIA_NODISCARD
constexpr bool operator!=(
const sarr_ext& other)
const noexcept {
451 return !operator==(other);