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>
66#if RANGES_BROKEN_CPO_LOOKUP
67 :
private _common_iterator_::adl_hook
73 CPP_assert(!same_as<I, S>);
81 template<
typename T, std::
size_t N>
84 ranges::emplace<N>(*data_, t.get());
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>;
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>)
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>)
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);
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_)++;
202#if !RANGES_BROKEN_CPO_LOOKUP
203 template<
typename I_ = 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(
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>
238 auto iter_swap(common_iterator<I1, S1>
const & x,
239 common_iterator<I2, S2>
const & y)
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)(
252 requires sentinel_for<S1, I2> AND sentinel_for<S2, I1> AND
253 (!equality_comparable_with<I1, I2>))
254 bool operator==(common_iterator<I1, S1>
const & x, common_iterator<I2, S2>
const & y)
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)(
265 requires sentinel_for<S1, I2> AND sentinel_for<S2, I1> AND
266 equality_comparable_with<I1, I2>)
267 bool operator==(common_iterator<I1, S1>
const & x, common_iterator<I2, S2>
const & y)
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)(
281 requires sentinel_for<S1, I2> AND sentinel_for<S2, I1>)
282 bool operator!=(common_iterator<I1, S1>
const & x, common_iterator<I2, S2>
const & y)
287 template(
typename I1,
typename I2,
typename S1,
typename S2)(
288 requires sized_sentinel_for<I1, I2> AND sized_sentinel_for<S1, I2> AND
289 sized_sentinel_for<S2, I1>)
290 iter_difference_t<I2>
operator-(common_iterator<I1, S1>
const & x,
291 common_iterator<I2, S2>
const & y)
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>
306 struct indirectly_readable_traits<common_iterator<I, S>>
308 (bool)indirectly_readable<I>,
309 indirectly_readable_traits<I>,
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);
446RANGES_DIAGNOSTIC_PUSH
447RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
451 template<
typename I,
typename 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.
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 common_iterator.hpp:69
Definition variant.hpp:71
Definition access.hpp:290
Definition variant.hpp:621