214 static_assert(mem::is_soa_layout_v<T>,
"sarr_ext_soa can be used only with soa types");
217 static_assert(
N > 0);
219 using value_type = T;
220 using reference = T&;
221 using const_reference =
const T&;
223 using const_pointer =
const T*;
226 using size_type = sarr_ext_soa_detail::size_type;
232 static constexpr size_type extent =
N;
233 static constexpr uint32_t allocated_bytes = view_policy::get_min_byte_size(0,
N);
237 size_type m_cnt = size_type(0);
245 constexpr sarr_ext_soa(size_type count, const_reference value)
noexcept {
246 resize(count, value);
253 template <
typename InputIt>
255 const auto count = (size_type)core::distance(first, last);
258 if constexpr (std::is_pointer_v<InputIt>) {
259 for (size_type
i = 0;
i < count; ++
i)
260 operator[](
i) = first[
i];
261 }
else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
262 for (size_type
i = 0;
i < count; ++
i)
263 operator[](
i) = *(first[
i]);
266 for (
auto it = first;
it != last; ++
it)
267 operator[](++
i) = *
it;
276 GAIA_ASSERT(core::addressof(other) !=
this);
278 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
280 other.m_cnt = size_type(0);
289 GAIA_ASSERT(core::addressof(other) !=
this);
291 resize(other.size());
292 mem::copy_elements<T, true>(
293 GAIA_ACC((
uint8_t*)&m_data[0]), GAIA_ACC((
const uint8_t*)&other.m_data[0]), other.size(), 0, extent,
300 GAIA_ASSERT(core::addressof(other) !=
this);
303 mem::move_elements<T, true>(
304 GAIA_ACC((
uint8_t*)&m_data[0]), GAIA_ACC((
uint8_t*)&other.m_data[0]), other.size(), 0, extent,
307 other.m_cnt = size_type(0);
312 GAIA_CLANG_WARNING_PUSH()
314 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
316 GAIA_NODISCARD
constexpr pointer data()
noexcept {
317 return GAIA_ACC((pointer)&m_data[0]);
320 GAIA_NODISCARD
constexpr const_pointer data()
const noexcept {
321 return GAIA_ACC((const_pointer)&m_data[0]);
324 GAIA_NODISCARD
constexpr decltype(
auto)
operator[](size_type pos)
noexcept {
325 GAIA_ASSERT(pos < size());
326 return view_policy::set({GAIA_ACC((
typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
329 GAIA_NODISCARD
constexpr decltype(
auto)
operator[](size_type pos)
const noexcept {
330 GAIA_ASSERT(pos < size());
331 return view_policy::get({GAIA_ACC((
typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
334 GAIA_CLANG_WARNING_POP()
336 constexpr void push_back(
const T& arg)
noexcept {
337 GAIA_ASSERT(size() <
N);
339 operator[](m_cnt++) = arg;
342 constexpr void push_back(T&& arg)
noexcept {
343 GAIA_ASSERT(size() <
N);
345 operator[](m_cnt++) = GAIA_MOV(arg);
348 template <
typename...
Args>
349 constexpr decltype(
auto) emplace_back(
Args&&...
args)
noexcept {
350 GAIA_ASSERT(size() <
N);
352 operator[](m_cnt++) = T(GAIA_FWD(
args)...);
355 constexpr void pop_back()
noexcept {
356 GAIA_ASSERT(!empty());
365 GAIA_ASSERT(size() <
N);
366 GAIA_ASSERT(pos >= data());
367 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
369 const auto idxSrc = (size_type)core::distance(begin(), pos);
370 const auto idxDst = (size_type)core::distance(begin(), end());
372 mem::shift_elements_right<T, true>(m_data,
idxDst,
idxSrc, extent);
385 GAIA_ASSERT(size() <
N);
386 GAIA_ASSERT(pos >= data());
387 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
389 const auto idxSrc = (size_type)core::distance(begin(), pos);
390 const auto idxDst = (size_type)core::distance(begin(), end());
392 mem::shift_elements_right<T, true>(m_data,
idxDst,
idxSrc, extent);
394 operator[](
idxSrc) = GAIA_MOV(arg);
404 GAIA_ASSERT(pos >= data());
405 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
410 const auto idxSrc = (size_type)core::distance(begin(), pos);
411 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
413 mem::shift_elements_left<T, true>(m_data,
idxDst,
idxSrc, extent);
424 GAIA_ASSERT(first >= data())
425 GAIA_ASSERT(empty() || (first <
iterator(data() + size())));
426 GAIA_ASSERT(last > first);
427 GAIA_ASSERT(last <= (data() + size()));
432 const auto idxSrc = (size_type)core::distance(begin(), first);
433 const auto idxDst = size();
434 const auto cnt = (size_type)(last - first);
436 mem::shift_elements_left_fast<T, true>(m_data,
idxDst,
idxSrc, cnt, extent);
445 GAIA_ASSERT(pos < size());
448 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
450 mem::shift_elements_left<T, true>(m_data,
idxDst,
idxSrc, extent);
461 constexpr void resize(size_type count)
noexcept {
462 GAIA_ASSERT(count <= max_size());
467 constexpr void resize(size_type count, const_reference value)
noexcept {
468 const auto oldCount = m_cnt;
471 if constexpr (std::is_copy_constructible_v<value_type>) {
472 const value_type valueCopy = value;
473 for (size_type i = oldCount; i < m_cnt; ++i)
474 operator[](i) = valueCopy;
476 for (size_type i = oldCount; i < m_cnt; ++i)
477 operator[](i) = value;
484 template <
typename Func>
491 if (func(
operator[](
idxSrc))) {
494 mem::move_element<T, true>(ptr, ptr,
idxDst,
idxSrc, max_size(), max_size());
496 core::call_dtor(
ptr2);
500 auto* ptr = &data()[
idxSrc];
501 core::call_dtor(ptr);
516 GAIA_NODISCARD
constexpr bool empty() const noexcept {
520 GAIA_NODISCARD
constexpr size_type capacity() const noexcept {
524 GAIA_NODISCARD
constexpr size_type max_size() const noexcept {
528 GAIA_NODISCARD
constexpr decltype(
auto) front() noexcept {
529 GAIA_ASSERT(!empty());
533 GAIA_NODISCARD
constexpr decltype(
auto) front() const noexcept {
534 GAIA_ASSERT(!empty());
538 GAIA_NODISCARD
constexpr decltype(
auto) back() noexcept {
539 GAIA_ASSERT(!empty());
540 return (
operator[])(m_cnt - 1);
543 GAIA_NODISCARD
constexpr decltype(
auto) back() const noexcept {
544 GAIA_ASSERT(!empty());
545 return operator[](m_cnt - 1);
548 GAIA_NODISCARD
constexpr auto begin() noexcept {
549 return iterator(GAIA_ACC(&m_data[0]), extent, 0);
552 GAIA_NODISCARD
constexpr auto begin() const noexcept {
553 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
556 GAIA_NODISCARD
constexpr auto cbegin() const noexcept {
557 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
560 GAIA_NODISCARD
constexpr auto rbegin() noexcept {
561 return iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
564 GAIA_NODISCARD
constexpr auto rbegin() const noexcept {
565 return const_iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
568 GAIA_NODISCARD
constexpr auto crbegin() const noexcept {
569 return const_iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
572 GAIA_NODISCARD
constexpr auto end() noexcept {
573 return iterator(GAIA_ACC(&m_data[0]), extent, size());
576 GAIA_NODISCARD
constexpr auto end() const noexcept {
577 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
580 GAIA_NODISCARD
constexpr auto cend() const noexcept {
581 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
584 GAIA_NODISCARD
constexpr auto rend() noexcept {
585 return iterator(GAIA_ACC(&m_data[0]), extent, -1);
588 GAIA_NODISCARD
constexpr auto rend() const noexcept {
589 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
592 GAIA_NODISCARD
constexpr auto crend() const noexcept {
593 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
596 GAIA_NODISCARD
constexpr bool operator==(
const sarr_ext_soa& other)
const noexcept {
597 if (m_cnt != other.m_cnt)
599 const size_type n = size();
600 for (size_type i = 0; i < n; ++i)
601 if (!(
operator[](i) == other[i]))
606 GAIA_NODISCARD
constexpr bool operator!=(
const sarr_ext_soa& other)
const noexcept {
607 return !operator==(other);
610 template <
size_t Item>
611 auto view_mut() noexcept {
612 return mem::data_view_policy<T::gaia_Data_Layout, T>::template set<Item>(
616 template <
size_t Item>
617 auto view() const noexcept {
618 return mem::data_view_policy<T::gaia_Data_Layout, T>::template get<Item>(