File indexing completed on 2025-07-09 07:49:52
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(iterator_t iterator) : m_iterator(iterator) {}
0174
0175 TransformRangeIterator() = default;
0176
0177
0178
0179 reference operator*() { return Callable::apply(*m_iterator); }
0180
0181
0182
0183 reference operator*() const { return Callable::apply(*m_iterator); }
0184
0185
0186
0187 TransformRangeIterator& operator++() {
0188 ++m_iterator;
0189 return *this;
0190 }
0191
0192
0193
0194 TransformRangeIterator operator++(int) {
0195 auto tmp = *this;
0196 ++m_iterator;
0197 return tmp;
0198 }
0199
0200
0201
0202 template <typename I, bool F>
0203 bool operator==(const TransformRangeIterator<Callable, I, F>& other) const
0204 requires(std::equality_comparable_with<iterator_t, I>)
0205 {
0206 return m_iterator == other.m_iterator;
0207 }
0208
0209 template <typename C, typename I, bool F>
0210 friend struct TransformRangeIterator;
0211
0212 private:
0213 iterator_t m_iterator;
0214 };
0215
0216
0217 struct Dereference {
0218 template <typename input_t>
0219 constexpr static decltype(auto) apply(input_t&& value) {
0220 return *value;
0221 }
0222 };
0223
0224
0225 struct ConstDereference {
0226 template <typename input_t>
0227 constexpr static decltype(auto) apply(input_t&& value) {
0228 return std::as_const(*value);
0229 }
0230 };
0231
0232
0233 struct DotGet {
0234 template <typename input_t>
0235 constexpr static decltype(auto) apply(input_t&& value) {
0236 return value.get();
0237 }
0238 };
0239
0240 }
0241
0242
0243 template <typename Callable, typename container_t>
0244 constexpr bool std::ranges::enable_borrowed_range<
0245 Acts::detail::TransformRange<Callable, container_t>> = true;
0246