File indexing completed on 2025-10-13 08:16:05
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Utilities/TypeTraits.hpp"
0012 #include "Acts/Utilities/detail/ContainerConcepts.hpp"
0013
0014 #include <span>
0015 #include <stdexcept>
0016
0017 namespace Acts::detail {
0018
0019 template <typename Derived, typename DerivedReadOnly, typename Container,
0020 typename Value, typename Index, bool ReadOnly>
0021 class ContainerSubset {
0022 public:
0023 using container_type = const_if_t<ReadOnly, Container>;
0024 using value_type = Value;
0025 using index_type = Index;
0026 static constexpr bool read_only = ReadOnly;
0027 using index_subset_type = std::span<const index_type>;
0028
0029 class Iterator {
0030 public:
0031 using subset_iterator = index_subset_type::iterator;
0032
0033 using value_type = Value;
0034 using difference_type = std::ptrdiff_t;
0035 using pointer = void;
0036 using reference = void;
0037
0038 using iterator_category = std::random_access_iterator_tag;
0039 using iterator_concept = std::random_access_iterator_tag;
0040
0041 constexpr Iterator() noexcept = default;
0042 constexpr Iterator(container_type &container,
0043 subset_iterator iterator) noexcept
0044 : m_container(&container), m_iterator(iterator) {}
0045
0046 constexpr value_type operator*() const {
0047 static_assert(
0048 ContainerHasAt<Container> || ContainerHasArrayAccess<Container>,
0049 "Container must support at() or operator[] for indexing");
0050 constexpr bool HasArrayAccess = ContainerHasArrayAccess<Container>;
0051
0052 if constexpr (HasArrayAccess) {
0053 return (*m_container)[*m_iterator];
0054 } else {
0055 return m_container->at(*m_iterator);
0056 }
0057 }
0058 constexpr value_type operator[](difference_type n) const {
0059 static_assert(
0060 ContainerHasAt<Container> || ContainerHasArrayAccess<Container>,
0061 "Container must support at() or operator[] for indexing");
0062 constexpr bool HasArrayAccess = ContainerHasArrayAccess<Container>;
0063
0064 if constexpr (HasArrayAccess) {
0065 return (*m_container)[m_iterator[n]];
0066 } else {
0067 return m_container->at(m_iterator[n]);
0068 }
0069 }
0070
0071 constexpr Iterator &operator++() noexcept {
0072 ++m_iterator;
0073 return *this;
0074 }
0075 constexpr Iterator operator++(int) noexcept {
0076 auto tmp = *this;
0077 ++(*this);
0078 return tmp;
0079 }
0080 constexpr Iterator &operator--() noexcept {
0081 --m_iterator;
0082 return *this;
0083 }
0084 constexpr Iterator operator--(int) noexcept {
0085 auto tmp = *this;
0086 --(*this);
0087 return tmp;
0088 }
0089
0090 constexpr Iterator &operator+=(difference_type n) noexcept {
0091 m_iterator += n;
0092 return *this;
0093 }
0094 constexpr Iterator &operator-=(difference_type n) noexcept {
0095 m_iterator -= n;
0096 return *this;
0097 }
0098
0099 private:
0100 container_type *m_container{};
0101 subset_iterator m_iterator{};
0102
0103 friend constexpr Iterator operator+(Iterator it,
0104 difference_type n) noexcept {
0105 return it += n;
0106 }
0107
0108 friend constexpr Iterator operator+(difference_type n,
0109 Iterator it) noexcept {
0110 return it += n;
0111 }
0112
0113 friend constexpr Iterator operator-(Iterator it,
0114 difference_type n) noexcept {
0115 return it -= n;
0116 }
0117
0118 friend constexpr difference_type operator-(const Iterator &lhs,
0119 const Iterator &rhs) noexcept {
0120 return lhs.m_iterator - rhs.m_iterator;
0121 }
0122
0123 friend constexpr auto operator<=>(const Iterator &a,
0124 const Iterator &b) noexcept {
0125 if (a.m_iterator < b.m_iterator) {
0126 return std::strong_ordering::less;
0127 }
0128 if (a.m_iterator > b.m_iterator) {
0129 return std::strong_ordering::greater;
0130 }
0131 return std::strong_ordering::equal;
0132 }
0133 friend constexpr bool operator==(const Iterator &a,
0134 const Iterator &b) noexcept {
0135 return a.m_iterator == b.m_iterator;
0136 }
0137 };
0138 using iterator = Iterator;
0139
0140 constexpr ContainerSubset(container_type &container,
0141 const index_subset_type &subset) noexcept
0142 : m_container(&container), m_subset(subset) {}
0143 template <bool OtherReadOnly>
0144 explicit constexpr ContainerSubset(
0145 const ContainerSubset<Derived, DerivedReadOnly, Container, Value, Index,
0146 OtherReadOnly> &other) noexcept
0147 requires(ReadOnly && !OtherReadOnly)
0148 : m_container(&other.container()), m_subset(other.subset()) {}
0149
0150 constexpr DerivedReadOnly asConst() const noexcept
0151 requires(!ReadOnly)
0152 {
0153 return {*m_container, m_subset};
0154 }
0155
0156 constexpr container_type &container() const noexcept { return *m_container; }
0157 constexpr const index_subset_type &subset() const noexcept {
0158 return m_subset;
0159 }
0160
0161 constexpr std::size_t size() const noexcept { return m_subset.size(); }
0162 constexpr bool empty() const noexcept { return size() == 0; }
0163
0164 constexpr Derived subrange(std::size_t offset) const noexcept {
0165 return {container(), m_subset.subspan(offset)};
0166 }
0167 constexpr Derived subrange(std::size_t offset,
0168 std::size_t count) const noexcept {
0169 return {container(), m_subset.subspan(offset, count)};
0170 }
0171
0172 constexpr auto front() const noexcept {
0173 return container()[m_subset.front()];
0174 }
0175 constexpr auto back() const noexcept { return container()[m_subset.back()]; }
0176
0177 constexpr iterator begin() const noexcept {
0178 return iterator(*m_container, m_subset.begin());
0179 }
0180 constexpr iterator end() const noexcept {
0181 return iterator(*m_container, m_subset.end());
0182 }
0183
0184 constexpr auto operator[](Index index) const noexcept
0185 requires(ContainerHasArrayAccess<Container>)
0186 {
0187 assert(index < size() && "Index out of bounds");
0188 return (*m_container)[m_subset[index]];
0189 }
0190 constexpr auto at(Index index) const
0191 requires(ContainerHasAt<Container>)
0192 {
0193 if (index >= size()) {
0194 throw std::out_of_range("Index out of bounds");
0195 }
0196 return m_container->at(m_subset[index]);
0197 }
0198
0199 private:
0200 container_type *m_container{};
0201 index_subset_type m_subset{};
0202 };
0203
0204 }