Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-13 08:16:05

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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 }  // namespace Acts::detail