Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /acts/Core/include/Acts/Utilities/Enumerate.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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 <cstddef>
0012 #include <iterator>
0013 #include <ranges>
0014 #include <tuple>
0015 #include <type_traits>
0016 #include <utility>
0017 
0018 namespace Acts {
0019 
0020 namespace detail {
0021 
0022 /// Deduce the index type from the container's `size()` (via `std::size`),
0023 /// falling back to `std::size_t` for ranges without a size (e.g. input
0024 /// ranges).
0025 template <typename T, typename = void>
0026 struct EnumerateIndexType {
0027   using type = std::size_t;
0028 };
0029 template <typename T>
0030 struct EnumerateIndexType<T,
0031                           std::void_t<decltype(std::size(std::declval<T>()))>> {
0032   using type = decltype(std::size(std::declval<T>()));
0033 };
0034 
0035 /// Iterator pairing an index with the element of an underlying iterator.
0036 ///
0037 /// This is a LegacyInputIterator: the element reference is a proxy (a tuple),
0038 /// which is why it cannot model the C++20 `std::forward_iterator` concept (in
0039 /// C++20 `std::tuple` lacks the `common_reference` support that C++23 adds).
0040 template <typename index_type, typename iterator_t>
0041 struct EnumerateIterator {
0042   using iterator_category = std::input_iterator_tag;
0043   using value_type = std::tuple<index_type, std::iter_value_t<iterator_t>>;
0044   using reference = std::tuple<index_type, std::iter_reference_t<iterator_t>>;
0045   using pointer = void;
0046   using difference_type = std::iter_difference_t<iterator_t>;
0047 
0048   index_type i;
0049   iterator_t iter;
0050 
0051   bool operator==(const EnumerateIterator &rhs) const {
0052     return iter == rhs.iter;
0053   }
0054 
0055   /// Pre-increment: advance index and underlying iterator together.
0056   EnumerateIterator &operator++() {
0057     ++i;
0058     ++iter;
0059     return *this;
0060   }
0061 
0062   /// Post-increment.
0063   EnumerateIterator operator++(int) {
0064     EnumerateIterator tmp = *this;
0065     ++*this;
0066     return tmp;
0067   }
0068 
0069   reference operator*() const { return reference{i, *iter}; }
0070 };
0071 
0072 /// Range wrapper that yields `EnumerateIterator`s over a (possibly owned)
0073 /// container.
0074 template <std::ranges::range container_type, typename index_type,
0075           typename iterator_t>
0076 struct EnumerateWrapper {
0077   container_type iterable;
0078   auto begin() {
0079     return EnumerateIterator<index_type, iterator_t>{0, std::begin(iterable)};
0080   }
0081   auto end() {
0082     return EnumerateIterator<index_type, iterator_t>{0, std::end(iterable)};
0083   }
0084 };
0085 
0086 }  // namespace detail
0087 
0088 /// Helper utility to allow indexed enumeration with structured binding
0089 ///
0090 /// Usage:
0091 ///
0092 /// for (auto [ i, value ] : enumerate(container) ) { ... };
0093 ///
0094 /// with 'container' any stl-like container
0095 /// @param iterable Container to enumerate
0096 /// @return Enumerable wrapper with index and value pairs
0097 template <std::ranges::range container_type,
0098           typename index_type =
0099               typename detail::EnumerateIndexType<container_type>::type,
0100           typename container_type_iter =
0101               decltype(std::begin(std::declval<container_type>()))>
0102 constexpr auto enumerate(container_type &&iterable) {
0103   return detail::EnumerateWrapper<container_type, index_type,
0104                                   container_type_iter>{
0105       std::forward<container_type>(iterable)};
0106 }
0107 
0108 }  // namespace Acts