File indexing completed on 2026-07-24 08:38:31
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <concepts>
0012 #include <iterator>
0013 #include <ranges>
0014 #include <type_traits>
0015 #include <utility>
0016
0017 namespace Acts::detail {
0018
0019 template <typename Callable, typename iterator_t, bool force_const>
0020 struct TransformRangeIterator;
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 template <typename Callable, typename container_t>
0036 struct TransformRange : public std::ranges::view_interface<
0037 TransformRange<Callable, container_t>> {
0038 private:
0039 using internal_value_type = typename container_t::value_type;
0040
0041 static_assert(std::is_reference_v<decltype(Callable::apply(
0042 std::declval<internal_value_type>()))>,
0043 "The callable must return a reference type");
0044
0045 using raw_value_type = std::remove_reference_t<decltype(Callable::apply(
0046 std::declval<internal_value_type>()))>;
0047
0048 public:
0049
0050
0051
0052 using value_type =
0053 std::conditional_t<std::is_const_v<container_t>,
0054 std::add_const_t<raw_value_type>, raw_value_type>;
0055
0056 using reference = value_type&;
0057 using const_reference = const value_type&;
0058
0059 using iterator = TransformRangeIterator<
0060 Callable,
0061 std::conditional_t<std::is_const_v<container_t>,
0062 typename container_t::const_iterator,
0063 typename container_t::iterator>,
0064 std::is_const_v<container_t>>;
0065 using const_iterator =
0066 TransformRangeIterator<Callable, typename container_t::const_iterator,
0067 true>;
0068
0069
0070
0071
0072 TransformRange(Callable&& , container_t& container)
0073 : m_container(&container) {}
0074
0075
0076
0077 explicit TransformRange(container_t& container) : m_container(&container) {}
0078
0079
0080
0081
0082
0083 reference operator[](std::size_t i) {
0084 return Callable::apply((*m_container)[i]);
0085 }
0086
0087
0088
0089
0090
0091 const_reference operator[](std::size_t i) const {
0092 return std::as_const(Callable::apply((*m_container)[i]));
0093 }
0094
0095
0096
0097
0098
0099 reference at(std::size_t i) { return Callable::apply(m_container->at(i)); }
0100
0101
0102
0103
0104
0105 const_reference at(std::size_t i) const {
0106 return std::as_const(Callable::apply(m_container->at(i)));
0107 }
0108
0109
0110
0111 iterator begin() { return iterator{m_container->begin()}; }
0112
0113
0114
0115 iterator end() { return iterator{m_container->end()}; }
0116
0117
0118
0119 const_iterator begin() const { return const_iterator{m_container->begin()}; }
0120
0121
0122
0123 const_iterator cbegin() const { return begin(); }
0124
0125
0126
0127 const_iterator end() const { return const_iterator{m_container->end()}; }
0128
0129
0130
0131 const_iterator cend() const { return end(); }
0132
0133
0134
0135 std::size_t size() const { return m_container->size(); }
0136
0137
0138
0139 bool empty() const { return m_container->empty(); }
0140
0141 private:
0142 container_t* m_container;
0143 };
0144
0145
0146
0147
0148
0149
0150
0151 template <typename Callable, typename iterator_t, bool force_const>
0152 struct TransformRangeIterator {
0153 private:
0154 using internal_value_type = typename std::iter_value_t<iterator_t>;
0155
0156 using raw_value_type = std::remove_reference_t<decltype(Callable::apply(
0157 std::declval<internal_value_type>()))>;
0158
0159 public:
0160
0161
0162
0163 using value_type =
0164 std::conditional_t<force_const, std::add_const_t<raw_value_type>,
0165 raw_value_type>;
0166
0167 using difference_type = typename std::iter_difference_t<iterator_t>;
0168 using pointer = std::remove_reference_t<value_type>*;
0169 using reference = value_type&;
0170 using iterator_category = std::forward_iterator_tag;
0171
0172
0173 explicit TransformRangeIterator(const iterator_t& iterator)
0174 : m_iterator(iterator) {}
0175
0176 TransformRangeIterator() = default;
0177
0178
0179
0180 reference operator*() { return Callable::apply(*m_iterator); }
0181
0182
0183
0184 reference operator*() const { return Callable::apply(*m_iterator); }
0185
0186
0187
0188 TransformRangeIterator& operator++() {
0189 ++m_iterator;
0190 return *this;
0191 }
0192
0193
0194
0195 TransformRangeIterator operator++(int) {
0196 auto tmp = *this;
0197 ++m_iterator;
0198 return tmp;
0199 }
0200
0201
0202
0203 template <typename I, bool F>
0204 bool operator==(const TransformRangeIterator<Callable, I, F>& other) const
0205 requires(std::equality_comparable_with<iterator_t, I>)
0206 {
0207 return m_iterator == other.m_iterator;
0208 }
0209
0210 template <typename C, typename I, bool F>
0211 friend struct TransformRangeIterator;
0212
0213 private:
0214 iterator_t m_iterator;
0215 };
0216
0217
0218 struct Dereference {
0219 template <typename input_t>
0220 constexpr static decltype(auto) apply(input_t&& value) {
0221 return *value;
0222 }
0223 };
0224
0225
0226 struct ConstDereference {
0227 template <typename input_t>
0228 constexpr static decltype(auto) apply(input_t&& value) {
0229 return std::as_const(*value);
0230 }
0231 };
0232
0233
0234 struct DotGet {
0235 template <typename input_t>
0236 constexpr static decltype(auto) apply(input_t&& value) {
0237 return value.get();
0238 }
0239 };
0240
0241 }
0242
0243
0244 template <typename Callable, typename container_t>
0245 constexpr bool std::ranges::enable_borrowed_range<
0246 Acts::detail::TransformRange<Callable, container_t>> = true;
0247