7namespace nc::algo::detail {
9consteval auto iter_cat()
11 if constexpr ((std::ranges::random_access_range<V> && ...))
13 return std::random_access_iterator_tag{};
15 else if constexpr ((std::ranges::bidirectional_range<V> && ...))
17 return std::bidirectional_iterator_tag{};
19 else if constexpr ((std::ranges::forward_range<V> && ...))
21 return std::forward_iterator_tag{};
23 else if constexpr ((std::ranges::input_range<V> && ...))
25 return std::input_iterator_tag{};
29 return std::output_iterator_tag{};
35 std::ranges::view<R> &&
36 std::ranges::range<const R> &&
37 std::same_as<std::ranges::iterator_t<R>, std::ranges::iterator_t<const R>> &&
38 std::same_as<std::ranges::sentinel_t<R>, std::ranges::sentinel_t<const R>>;
40template<std::ranges::input_range V>
41 requires std::ranges::view<V>
54 using Base = std::conditional_t<Const, const V, V>;
55 using count_type =
decltype([] {
56 if constexpr (std::ranges::sized_range<Base>)
57 return std::ranges::range_size_t<Base>();
59 return std::make_unsigned_t<std::ranges::range_difference_t<Base>>();
66 const count_type index;
69 constexpr bool operator==(
const result& other)
const =
default;
72 std::ranges::iterator_t<Base> m_it = std::ranges::iterator_t<Base>();
76 friend struct iterator;
78 friend struct sentinel;
81 using iterator_category =
decltype(iter_cat<Base>());
82 using reference = result<std::ranges::range_reference_t<Base>>;
83 using value_type = result<std::ranges::range_reference_t<Base>>;
84 using difference_type = std::ranges::range_difference_t<Base>;
88 constexpr explicit iterator(std::ranges::iterator_t<Base> current, std::ranges::range_difference_t<Base> pos)
89 : m_it(std::move(current)),
90 m_pos(
static_cast<count_type
>(pos))
94 constexpr iterator(iterator<!Const> i)
96 std::convertible_to<std::ranges::iterator_t<V>, std::ranges::iterator_t<Base>>
97 : m_it(std::move(i.m_it)),
102 constexpr auto base()
const & ->
const std::ranges::iterator_t<V>&
103 requires std::copyable<std::ranges::iterator_t<Base>>
108 constexpr auto base() && -> std::ranges::iterator_t<V>
110 return std::move(m_it);
113 constexpr auto operator*()
const
115 return reference{
static_cast<count_type
>(m_pos), *m_it};
118 constexpr auto operator++() -> iterator&
125 constexpr auto operator++(
int)
128 if constexpr (std::ranges::forward_range<V>)
140 constexpr auto operator--() -> iterator&
141 requires std::ranges::bidirectional_range<V>
148 constexpr auto operator--(
int)
149 requires std::ranges::bidirectional_range<V>
156 constexpr auto operator+=(difference_type n) -> iterator&
157 requires std::ranges::random_access_range<V>
164 constexpr auto operator-=(difference_type n) -> iterator&
165 requires std::ranges::random_access_range<V>
172 friend constexpr auto operator+(
const iterator& i, difference_type n) -> iterator
173 requires std::ranges::random_access_range<V>
175 return iterator{i.m_it + n,
static_cast<difference_type
>(i.m_pos + n)};
178 friend constexpr auto operator+(difference_type n,
const iterator &i) -> iterator
179 requires std::ranges::random_access_range<V>
181 return iterator{i.m_it + n,
static_cast<difference_type
>(i.m_pos + n)};
184 friend constexpr auto operator-(iterator i, difference_type n)
185 requires std::ranges::random_access_range<V>
187 return iterator{i.m_it - n,
static_cast<difference_type
>(i.m_pos - n)};
190 friend constexpr auto operator-(difference_type n, iterator i)
191 requires std::ranges::random_access_range<V>
193 return iterator{i.m_it - n,
static_cast<difference_type
>(i.m_pos - n)};
196 constexpr decltype(
auto)
operator[](difference_type n)
const
197 requires std::ranges::random_access_range<Base>
199 return reference{
static_cast<count_type
>(m_pos + n), *(m_it + n)};
202 friend constexpr auto operator==(
const iterator& x,
const iterator& y) ->
bool
203 requires std::equality_comparable<std::ranges::iterator_t<Base>>
205 return x.m_it == y.m_it;
208 template <
bool ConstS>
209 friend constexpr auto operator==(
const iterator<Const>& i,
const sentinel<ConstS>& s) ->
bool
211 return i.m_it == s.base();
214 friend constexpr auto operator<(
const iterator& x,
const iterator& y) ->
bool
215 requires std::ranges::random_access_range<Base>
217 return x.m_it < y.m_it;
220 friend constexpr auto operator>(
const iterator& x,
const iterator& y) ->
bool
221 requires std::ranges::random_access_range<Base>
223 return x.m_it > y.m_it;
226 friend constexpr auto operator<=(
const iterator& x,
const iterator& y) ->
bool
227 requires std::ranges::random_access_range<Base>
229 return x.m_it <= y.m_it;
232 friend constexpr auto operator>=(
const iterator& x,
const iterator& y) ->
bool
233 requires std::ranges::random_access_range<Base>
235 return x.m_it >= y.m_it;
238 friend constexpr auto operator<=>(
const iterator& x,
const iterator& y)
239 requires std::ranges::random_access_range<Base> &&
240 std::three_way_comparable<std::ranges::iterator_t<Base>>
242 return x.m_it <=> y.m_it;
245 friend constexpr auto operator-(
const iterator& x,
const iterator& y) -> difference_type
246 requires std::ranges::random_access_range<Base>
248 return x.m_it - y.m_it;
255 friend iterator<false>;
256 friend iterator<true>;
258 using Base = std::conditional_t<Const, const V, V>;
260 std::ranges::sentinel_t<V> end_;
263 sentinel() =
default;
265 constexpr explicit sentinel(std::ranges::sentinel_t<V> end)
266 : end_(std::move(end))
270 constexpr auto base()
const
275 friend constexpr auto operator-(
const iterator<Const> &x,
const sentinel &y) -> std::ranges::range_difference_t<Base>
276 requires std::sized_sentinel_for<std::ranges::sentinel_t<Base>, std::ranges::iterator_t<Base>> {
277 return x.m_it - y.end_;
280 friend constexpr auto operator-(
const sentinel &x,
const iterator<Const> &y) -> std::ranges::range_difference_t<Base>
281 requires std::sized_sentinel_for<std::ranges::sentinel_t<Base>, std::ranges::iterator_t<Base>>
283 return x.end_ - y.m_it;
290 : m_base(std::move(base))
294 constexpr auto begin()
requires(!simple_view<V>)
296 return iterator<false>(std::ranges::begin(m_base), 0);
299 constexpr auto begin()
const requires simple_view<V>
301 return iterator<true>(std::ranges::begin(m_base), 0);
306 return sentinel<false>{std::ranges::end(m_base)};
310 requires std::ranges::common_range<V>
312 return iterator<false>{std::ranges::end(m_base),
static_cast<std::ranges::range_difference_t<V>
>(size())};
315 constexpr auto end()
const
316 requires std::ranges::range<const V>
318 return sentinel<true>{std::ranges::end(m_base)};
321 constexpr auto end()
const
322 requires std::ranges::common_range<const V>
324 return iterator<true>{std::ranges::end(m_base),
static_cast<std::ranges::range_difference_t<V>
>(size())};
327 constexpr auto size()
requires std::ranges::sized_range<V>
329 return std::ranges::size(m_base);
332 constexpr auto size()
const
333 requires std::ranges::sized_range<const V>
335 return std::ranges::size(m_base);
338 constexpr auto base()
const & -> V
339 requires std::copyable<V>
344 constexpr V base() &&
346 return std::move(m_base);
356 constexpr auto operator()(R &&r)
const {
360 template<std::ranges::input_range R>
Definition: EnumerateDetail.h:43
Definition: EnumerateDetail.h:354