2#ifndef LIBSBX_ECS_DETAIL_STORAGE_ITERATOR_HPP_
3#define LIBSBX_ECS_DETAIL_STORAGE_ITERATOR_HPP_
9#include <libsbx/utility/fast_mod.hpp>
11#include <libsbx/memory/iterable_adaptor.hpp>
13namespace sbx::ecs::detail {
15template<
typename Container, std::
size_t Page>
20 using container_type = std::remove_const_t<Container>;
21 using allocator_traits = std::allocator_traits<typename container_type::allocator_type>;
23 using iterator_traits = std::iterator_traits<std::conditional_t<
24 std::is_const_v<Container>,
25 typename allocator_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::const_pointer,
26 typename allocator_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::pointer>
31 using value_type =
typename iterator_traits::value_type;
32 using pointer =
typename iterator_traits::pointer;
33 using reference =
typename iterator_traits::reference;
34 using difference_type =
typename iterator_traits::difference_type;
35 using iterator_category = std::random_access_iterator_tag;
39 constexpr storage_iterator(Container* container,
const difference_type offset) noexcept
40 : _container{container},
43 template<
bool IsConst = std::is_const_v<Container>>
54 const auto original = *
this;
65 const auto original = *
this;
70 constexpr auto operator+=(
const difference_type value)
noexcept ->
storage_iterator& {
75 constexpr auto operator+(
const difference_type value)
const noexcept ->
storage_iterator {
77 return (copy += value);
80 constexpr auto operator-=(
const difference_type value)
noexcept ->
storage_iterator& {
81 return (*
this += -value);
84 constexpr auto operator-(
const difference_type value)
const noexcept ->
storage_iterator {
85 return (*
this + -value);
88 [[nodiscard]]
constexpr reference operator[](
const difference_type value)
const noexcept {
89 const auto position =
static_cast<typename Container::size_type
>(index() - value);
90 return (*_container)[position / Page][utility::fast_mod(
static_cast<std::size_t
>(position), Page)];
93 [[nodiscard]]
constexpr pointer operator->()
const noexcept {
94 return std::addressof(
operator[](0));
97 [[nodiscard]]
constexpr reference operator*()
const noexcept {
101 [[nodiscard]]
constexpr difference_type index()
const noexcept {
107 Container* _container;
108 difference_type _offset;
112template<
typename Lhs,
typename Rhs, std::
size_t Page>
114 return lhs.index() == rhs.index();
117template<
typename Iterator,
typename... Other>
120 template<
typename It,
typename... Args>
123 template<
typename... Lhs,
typename... Rhs>
128 using iterator = Iterator;
129 using value_type =
decltype(std::tuple_cat(std::make_tuple(*std::declval<Iterator>()), std::forward_as_tuple(*std::declval<Other>()...)));
131 using reference = value_type;
132 using difference_type = std::ptrdiff_t;
133 using iterator_category = std::input_iterator_tag;
134 using iterator_concept = std::forward_iterator_tag;
140 : _values{base, other...} { }
142 template<
typename... Args,
typename = std::enable_if_t<(!std::is_same_v<Other, Args> && ...) && (std::is_constructible_v<Other, Args> && ...)>>
144 : _values{other._values} {}
147 return ++std::get<iterator>(_values), (++std::get<Other>(_values), ...), *
this;
151 const auto original = *
this;
156 [[nodiscard]]
constexpr auto operator->()
const noexcept ->
pointer {
160 [[nodiscard]]
constexpr auto operator*()
const noexcept -> reference {
161 return {*std::get<iterator>(_values), *std::get<Other>(_values)...};
164 [[nodiscard]]
constexpr auto base()
const noexcept -> iterator {
165 return std::get<iterator>(_values);
170 std::tuple<iterator, Other...> _values;
174template<
typename... Lhs,
typename... Rhs>
176 return std::get<0>(lhs._values) == std::get<0>(rhs._values);
Definition: storage_iterator.hpp:118
Definition: storage_iterator.hpp:16