14#ifndef RANGES_V3_ITERATOR_COMMON_ITERATOR_HPP
15#define RANGES_V3_ITERATOR_COMMON_ITERATOR_HPP
27#include <range/v3/detail/variant.hpp>
32#include <range/v3/detail/prologue.hpp>
42 template<
typename I,
typename S>
43 variant<I, S> & cidata(common_iterator<I, S> & that)
48 template<
typename I,
typename S>
49 variant<I, S>
const & cidata(common_iterator<I, S>
const & that)
55#if RANGES_BROKEN_CPO_LOOKUP
56 namespace _common_iterator_
64 template<
typename I,
typename S>
65 struct common_iterator
66#if RANGES_BROKEN_CPO_LOOKUP
67 :
private _common_iterator_::adl_hook
73 CPP_assert(!same_as<I, S>);
76 friend variant<I, S> & detail::cidata<>(common_iterator<I, S> &);
77 friend variant<I, S> const & detail::cidata<>(common_iterator<I, S>
const &);
81 template<
typename T, std::
size_t N>
84 ranges::emplace<N>(*data_, t.get());
90 friend common_iterator;
91 iter_value_t<I> keep_;
92 arrow_proxy_(iter_reference_t<I> && x)
97 const iter_value_t<I> * operator->()
const noexcept
99 return std::addressof(keep_);
103 static T * operator_arrow_(T * p,
int)
noexcept
107 template<
typename J,
typename = detail::iter_arrow_t<J const>>
108 static J operator_arrow_(J
const & j,
int)
noexcept(
noexcept(J(j)))
112 template(
typename J,
typename R = iter_reference_t<J>)(
113 requires std::is_reference<R>::value)
117 return std::addressof(r);
119 template(
typename J,
typename V = iter_value_t<J>)(
120 requires constructible_from<V, iter_reference_t<J>>)
121 static arrow_proxy_ operator_arrow_(J
const & j, ...)
noexcept(
noexcept(V(V(*j))))
123 return arrow_proxy_(*j);
127 using difference_type = iter_difference_t<I>;
129 common_iterator() =
default;
131 : data_(emplaced_index<0>, std::move(i))
134 : data_(emplaced_index<1>, std::move(s))
136 template(
typename I2,
typename S2)(
137 requires convertible_to<I2, I> AND convertible_to<S2, S>)
138 common_iterator(common_iterator<I2, S2>
const & that)
139 : data_(detail::variant_core_access::make_empty<I, S>())
141 detail::cidata(that).visit_i(emplace_fn{&data_});
143 template(
typename I2,
typename S2)(
144 requires convertible_to<I2, I> AND convertible_to<S2, S>)
145 common_iterator & operator=(common_iterator<I2, S2>
const & that)
147 detail::cidata(that).visit_i(emplace_fn{&data_});
150 iter_reference_t<I> operator*()
151 noexcept(
noexcept(iter_reference_t<I>(*std::declval<I &>())))
153 return *ranges::get<0>(data_);
156 auto operator*()
const
157 noexcept(
noexcept(iter_reference_t<I>(*std::declval<I const &>())))
158 -> CPP_ret(iter_reference_t<I>)(
161 return *ranges::get<0>(data_);
163 template(
typename J = I)(
165 auto operator->()
const
167 noexcept(common_iterator::operator_arrow_(std::declval<I const &>(), 42)))
168 ->
decltype(common_iterator::operator_arrow_(std::declval<J const &>(), 42))
170 return common_iterator::operator_arrow_(ranges::get<0>(data_), 42);
172 common_iterator & operator++()
174 ++ranges::get<0>(data_);
177#ifdef RANGES_WORKAROUND_MSVC_677925
178 template(
typename I2 = I)(
181 ->
decltype(std::declval<I2 &>()++)
183 return ranges::get<0>(data_)++;
188 -> CPP_ret(
decltype(std::declval<I &>()++))(
191 return ranges::get<0>(data_)++;
196 -> CPP_ret(common_iterator)(
199 return common_iterator(ranges::get<0>(data_)++);
202#if !RANGES_BROKEN_CPO_LOOKUP
203 template<
typename I_ = I>
204 friend constexpr auto iter_move(common_iterator
const & i)
205 noexcept(detail::has_nothrow_iter_move_v<I>)
206 -> CPP_broken_friend_ret(iter_rvalue_reference_t<I>)(
209 return ranges::iter_move(ranges::get<0>(detail::cidata(i)));
211 template<
typename I2,
typename S2>
212 friend auto iter_swap(
213 common_iterator
const & x,
214 common_iterator<I2, S2>
const &
216 -> CPP_broken_friend_ret(
void)(
219 return ranges::iter_swap(ranges::get<0>(detail::cidata(x)),
220 ranges::get<0>(detail::cidata(y)));
226#if RANGES_BROKEN_CPO_LOOKUP
227 namespace _common_iterator_
229 template<
typename I,
typename S>
231 detail::has_nothrow_iter_move_v<I>)
232 -> CPP_broken_friend_ret(iter_rvalue_reference_t<I>)(
235 return ranges::iter_move(ranges::get<0>(detail::cidata(i)));
237 template<
typename I1,
typename S1,
typename I2,
typename S2>
240 noexcept(is_nothrow_indirectly_swappable<I1, I2>::value)
241 -> CPP_broken_friend_ret(
void)(
242 requires indirectly_swappable<I1, I2>)
244 return ranges::iter_swap(ranges::get<0>(detail::cidata(x)),
245 ranges::get<0>(detail::cidata(y)));
251 template(
typename I1,
typename I2,
typename S1,
typename S2)(
253 (!equality_comparable_with<I1, I2>))
256 return detail::cidata(x).index() == 1u ? (detail::cidata(y).index() == 1u ||
257 ranges::get<0>(detail::cidata(y)) ==
258 ranges::get<1>(detail::cidata(x)))
259 : (detail::cidata(y).index() != 1u ||
260 ranges::get<0>(detail::cidata(x)) ==
261 ranges::get<1>(detail::cidata(y)));
264 template(
typename I1,
typename I2,
typename S1,
typename S2)(
266 equality_comparable_with<I1, I2>)
269 return detail::cidata(x).index() == 1u
270 ? (detail::cidata(y).index() == 1u ||
271 ranges::get<0>(detail::cidata(y)) ==
272 ranges::get<1>(detail::cidata(x)))
273 : (detail::cidata(y).index() == 1u
274 ? ranges::get<0>(detail::cidata(x)) ==
275 ranges::get<1>(detail::cidata(y))
276 : ranges::get<0>(detail::cidata(x)) ==
277 ranges::get<0>(detail::cidata(y)));
280 template(
typename I1,
typename I2,
typename S1,
typename S2)(
287 template(
typename I1,
typename I2,
typename S1,
typename S2)(
293 return detail::cidata(x).index() == 1u
294 ? (detail::cidata(y).index() == 1u
296 : ranges::get<1>(detail::cidata(x)) -
297 ranges::get<0>(detail::cidata(y)))
298 : (detail::cidata(y).index() == 1u
299 ? ranges::get<0>(detail::cidata(x)) -
300 ranges::get<1>(detail::cidata(y))
301 : ranges::get<0>(detail::cidata(x)) -
302 ranges::get<0>(detail::cidata(y)));
305 template<
typename I,
typename S>
317 auto demote_common_iter_cat(...) -> nil_;
319 auto demote_common_iter_cat(
long)
320 -> with_iterator_category<std::input_iterator_tag>;
321 template(
typename I)(
322 requires derived_from<
typename std::iterator_traits<I>::iterator_category,
323 std::forward_iterator_tag>)
324 auto demote_common_iter_cat(
int)
325 -> with_iterator_category<std::forward_iterator_tag>;
327 template<
typename I,
bool = (
bool)input_iterator<I>>
328 struct common_iterator_std_traits :
decltype(detail::demote_common_iter_cat<I>(0))
330 using difference_type = iter_difference_t<I>;
331 using value_type = iter_value_t<I>;
332 using reference = iter_reference_t<I>;
333 using pointer = detail::iter_pointer_t<I>;
334 using iterator_concept =
336 std::input_iterator_tag>;
340 struct common_iterator_std_traits<I, false>
342 using difference_type = iter_difference_t<I>;
343 using value_type = void;
344 using reference = void;
345 using pointer = void;
346 using iterator_category = std::output_iterator_tag;
353 struct cpp17_iterator_cursor
358 struct mixin : basic_mixin<cpp17_iterator_cursor>
362 using basic_mixin<cpp17_iterator_cursor>::basic_mixin;
364 constexpr explicit mixin(cpp17_iterator_cursor && cur)
365 : basic_mixin<cpp17_iterator_cursor>(
366 static_cast<cpp17_iterator_cursor &&>(cur))
368 constexpr explicit mixin(cpp17_iterator_cursor
const & cur)
369 : basic_mixin<cpp17_iterator_cursor>(cur)
373 : mixin{cpp17_iterator_cursor{std::move(it)}}
377 return this->get().it_;
383 using difference_type = std::ptrdiff_t;
384 using value_type = iter_value_t<I>;
386 cpp17_iterator_cursor() =
default;
387 constexpr explicit cpp17_iterator_cursor(I i)
388 : it_(static_cast<I &&>(i))
395 decltype(
auto) read()
399 decltype(
auto) read()
const
407 bool equal(cpp17_iterator_cursor
const & that)
const
409 return it_ == that.it_;
414 requires bidirectional_iterator<I>)
419 auto advance(std::ptrdiff_t n)
421 requires random_access_iterator<I>)
423 it_ +=
static_cast<iter_difference_t<I>
>(n);
426 auto distance_to(cpp17_iterator_cursor
const & that)
427 -> CPP_ret(std::ptrdiff_t)(
428 requires random_access_iterator<I>)
430 auto d = that.it_ - it_;
431 RANGES_EXPECT(d <= PTRDIFF_MAX);
432 return static_cast<std::ptrdiff_t
>(d);
440 using ranges::common_iterator;
446RANGES_DIAGNOSTIC_PUSH
447RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
451 template<
typename I,
typename S>
452 struct iterator_traits<::ranges::common_iterator<I, S>>
453 : ::ranges::detail::common_iterator_std_traits<I>
460#include <range/v3/detail/epilogue.hpp>
The forward_iterator concept.
The indirectly_readable concept.
The indirectly_swappable concept.
The sentinel_for concept.
The sized_sentinel_for concept.
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition meta.hpp:168
typename T::type _t
Type alias for T::type.
Definition meta.hpp:141
typename detail::_cond< If >::template invoke< Then, Else > conditional_t
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1148
Point operator-(const Point &a, const Point &b)
Subtract two points_ component-wise.
Definition shapes.h:244
Definition adjacent_find.hpp:67
Definition common_iterator.hpp:69
Definition common_iterator.hpp:69
Definition variant.hpp:71
Definition associated_types.hpp:236
Definition access.hpp:290
Definition variant.hpp:621