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 <stdexcept>
0015 #include <utility>
0016
0017 namespace Acts::detail {
0018
0019 template <typename Derived, typename DerivedReadOnly, typename Container,
0020 typename Index, bool ReadOnly>
0021 class ContainerRange {
0022 public:
0023 using container_type = const_if_t<ReadOnly, Container>;
0024 using index_type = Index;
0025 static constexpr bool read_only = ReadOnly;
0026 using index_range_type = std::pair<index_type, index_type>;
0027
0028 constexpr ContainerRange(container_type &container,
0029 const index_range_type &range) noexcept
0030 : m_container(&container), m_range(range) {}
0031 template <bool OtherReadOnly>
0032 explicit constexpr ContainerRange(
0033 const ContainerRange<Derived, DerivedReadOnly, Container, Index,
0034 OtherReadOnly> &other) noexcept
0035 requires(ReadOnly && !OtherReadOnly)
0036 : m_container(&other.container()), m_range(other.range()) {}
0037
0038 constexpr DerivedReadOnly asConst() const noexcept
0039 requires(!ReadOnly)
0040 {
0041 return {container(), range()};
0042 }
0043
0044 constexpr container_type &container() const noexcept { return *m_container; }
0045 constexpr const index_range_type &range() const noexcept { return m_range; }
0046
0047 constexpr std::size_t size() const noexcept {
0048 return m_range.second - m_range.first;
0049 }
0050 constexpr bool empty() const noexcept { return size() == 0; }
0051
0052 constexpr Derived subrange(index_type offset) const noexcept {
0053 assert(offset <= m_range.second - m_range.first &&
0054 "Subrange offset out of bounds");
0055 return {container(), {m_range.first + offset, m_range.second}};
0056 }
0057 constexpr Derived subrange(index_type offset,
0058 index_type count) const noexcept {
0059 assert(offset <= m_range.second - m_range.first &&
0060 "Subrange offset out of bounds");
0061 assert(count <= m_range.second - m_range.first - offset &&
0062 "Subrange count out of bounds");
0063 return {container(),
0064 {m_range.first + offset, m_range.first + offset + count}};
0065 }
0066
0067 constexpr auto front() const noexcept { return container()[m_range.first]; }
0068 constexpr auto back() const noexcept {
0069 return container()[m_range.second - 1];
0070 }
0071
0072 constexpr auto begin() const noexcept {
0073 return container().begin() + m_range.first;
0074 }
0075 constexpr auto end() const noexcept {
0076 return container().begin() + m_range.second;
0077 }
0078
0079 constexpr auto operator[](Index index) const noexcept
0080 requires(ContainerHasArrayAccess<Container>)
0081 {
0082 assert(index < size() && "Index out of bounds");
0083 return (*m_container)[m_range.first + index];
0084 }
0085 constexpr auto at(Index index) const
0086 requires(ContainerHasAt<Container>)
0087 {
0088 if (index >= size()) {
0089 throw std::out_of_range("Index out of bounds");
0090 }
0091 return m_container->at(m_range.first + index);
0092 }
0093
0094 private:
0095 container_type *m_container{};
0096 index_range_type m_range{};
0097 };
0098
0099 }