File indexing completed on 2025-01-18 10:09:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_ITERATOR_COMMON_ITERATOR_HPP
0015 #define RANGES_V3_ITERATOR_COMMON_ITERATOR_HPP
0016
0017 #include <cstdint>
0018 #include <iterator>
0019 #include <type_traits>
0020
0021 #include <meta/meta.hpp>
0022
0023 #include <concepts/concepts.hpp>
0024
0025 #include <range/v3/range_fwd.hpp>
0026
0027 #include <range/v3/detail/variant.hpp>
0028 #include <range/v3/iterator/basic_iterator.hpp>
0029 #include <range/v3/iterator/concepts.hpp>
0030 #include <range/v3/utility/common_tuple.hpp>
0031
0032 #include <range/v3/detail/prologue.hpp>
0033
0034 namespace ranges
0035 {
0036
0037
0038
0039
0040 namespace detail
0041 {
0042 template<typename I, typename S>
0043 variant<I, S> & cidata(common_iterator<I, S> & that)
0044 {
0045 return that.data_;
0046 }
0047
0048 template<typename I, typename S>
0049 variant<I, S> const & cidata(common_iterator<I, S> const & that)
0050 {
0051 return that.data_;
0052 }
0053 }
0054
0055 #if RANGES_BROKEN_CPO_LOOKUP
0056 namespace _common_iterator_
0057 {
0058 struct adl_hook
0059 {};
0060 }
0061 #endif
0062
0063
0064 template<typename I, typename S>
0065 struct common_iterator
0066 #if RANGES_BROKEN_CPO_LOOKUP
0067 : private _common_iterator_::adl_hook
0068 #endif
0069 {
0070 private:
0071 CPP_assert(input_or_output_iterator<I>);
0072 CPP_assert(sentinel_for<S, I>);
0073 CPP_assert(!same_as<I, S>);
0074 variant<I, S> data_;
0075
0076 friend variant<I, S> & detail::cidata<>(common_iterator<I, S> &);
0077 friend variant<I, S> const & detail::cidata<>(common_iterator<I, S> const &);
0078 struct emplace_fn
0079 {
0080 variant<I, S> * data_;
0081 template<typename T, std::size_t N>
0082 void operator()(indexed_element<T, N> t) const
0083 {
0084 ranges::emplace<N>(*data_, t.get());
0085 }
0086 };
0087 struct arrow_proxy_
0088 {
0089 private:
0090 friend common_iterator;
0091 iter_value_t<I> keep_;
0092 arrow_proxy_(iter_reference_t<I> && x)
0093 : keep_(std::move(x))
0094 {}
0095
0096 public:
0097 const iter_value_t<I> * operator->() const noexcept
0098 {
0099 return std::addressof(keep_);
0100 }
0101 };
0102 template<typename T>
0103 static T * operator_arrow_(T * p, int) noexcept
0104 {
0105 return p;
0106 }
0107 template<typename J, typename = detail::iter_arrow_t<J const>>
0108 static J operator_arrow_(J const & j, int) noexcept(noexcept(J(j)))
0109 {
0110 return j;
0111 }
0112 template(typename J, typename R = iter_reference_t<J>)(
0113 requires std::is_reference<R>::value)
0114 static meta::_t<std::add_pointer<R>> operator_arrow_(J const & j, long) noexcept
0115 {
0116 auto && r = *j;
0117 return std::addressof(r);
0118 }
0119 template(typename J, typename V = iter_value_t<J>)(
0120 requires constructible_from<V, iter_reference_t<J>>)
0121 static arrow_proxy_ operator_arrow_(J const & j, ...) noexcept(noexcept(V(V(*j))))
0122 {
0123 return arrow_proxy_(*j);
0124 }
0125
0126 public:
0127 using difference_type = iter_difference_t<I>;
0128
0129 common_iterator() = default;
0130 common_iterator(I i)
0131 : data_(emplaced_index<0>, std::move(i))
0132 {}
0133 common_iterator(S s)
0134 : data_(emplaced_index<1>, std::move(s))
0135 {}
0136 template(typename I2, typename S2)(
0137 requires convertible_to<I2, I> AND convertible_to<S2, S>)
0138 common_iterator(common_iterator<I2, S2> const & that)
0139 : data_(detail::variant_core_access::make_empty<I, S>())
0140 {
0141 detail::cidata(that).visit_i(emplace_fn{&data_});
0142 }
0143 template(typename I2, typename S2)(
0144 requires convertible_to<I2, I> AND convertible_to<S2, S>)
0145 common_iterator & operator=(common_iterator<I2, S2> const & that)
0146 {
0147 detail::cidata(that).visit_i(emplace_fn{&data_});
0148 return *this;
0149 }
0150 iter_reference_t<I> operator*()
0151 noexcept(noexcept(iter_reference_t<I>(*std::declval<I &>())))
0152 {
0153 return *ranges::get<0>(data_);
0154 }
0155 CPP_member
0156 auto operator*() const
0157 noexcept(noexcept(iter_reference_t<I>(*std::declval<I const &>())))
0158 -> CPP_ret(iter_reference_t<I>)(
0159 requires indirectly_readable<I const>)
0160 {
0161 return *ranges::get<0>(data_);
0162 }
0163 template(typename J = I)(
0164 requires indirectly_readable<J>)
0165 auto operator->() const
0166 noexcept(
0167 noexcept(common_iterator::operator_arrow_(std::declval<I const &>(), 42)))
0168 -> decltype(common_iterator::operator_arrow_(std::declval<J const &>(), 42))
0169 {
0170 return common_iterator::operator_arrow_(ranges::get<0>(data_), 42);
0171 }
0172 common_iterator & operator++()
0173 {
0174 ++ranges::get<0>(data_);
0175 return *this;
0176 }
0177 #ifdef RANGES_WORKAROUND_MSVC_677925
0178 template(typename I2 = I)(
0179 requires (!forward_iterator<I2>))
0180 auto operator++(int)
0181 -> decltype(std::declval<I2 &>()++)
0182 {
0183 return ranges::get<0>(data_)++;
0184 }
0185 #else
0186 CPP_member
0187 auto operator++(int)
0188 -> CPP_ret(decltype(std::declval<I &>()++))(
0189 requires (!forward_iterator<I>))
0190 {
0191 return ranges::get<0>(data_)++;
0192 }
0193 #endif
0194 CPP_member
0195 auto operator++(int)
0196 -> CPP_ret(common_iterator)(
0197 requires forward_iterator<I>)
0198 {
0199 return common_iterator(ranges::get<0>(data_)++);
0200 }
0201
0202 #if !RANGES_BROKEN_CPO_LOOKUP
0203 template<typename I_ = I>
0204 friend constexpr auto iter_move(common_iterator const & i)
0205 noexcept(detail::has_nothrow_iter_move_v<I>)
0206 -> CPP_broken_friend_ret(iter_rvalue_reference_t<I>)(
0207 requires input_iterator<I_>)
0208 {
0209 return ranges::iter_move(ranges::get<0>(detail::cidata(i)));
0210 }
0211 template<typename I2, typename S2>
0212 friend auto iter_swap(
0213 common_iterator const & x,
0214 common_iterator<I2, S2> const &
0215 y) noexcept(is_nothrow_indirectly_swappable<I, I2>::value)
0216 -> CPP_broken_friend_ret(void)(
0217 requires indirectly_swappable<I2, I>)
0218 {
0219 return ranges::iter_swap(ranges::get<0>(detail::cidata(x)),
0220 ranges::get<0>(detail::cidata(y)));
0221 }
0222 #endif
0223 };
0224
0225
0226 #if RANGES_BROKEN_CPO_LOOKUP
0227 namespace _common_iterator_
0228 {
0229 template<typename I, typename S>
0230 constexpr auto iter_move(common_iterator<I, S> const & i) noexcept(
0231 detail::has_nothrow_iter_move_v<I>)
0232 -> CPP_broken_friend_ret(iter_rvalue_reference_t<I>)(
0233 requires input_iterator<I>)
0234 {
0235 return ranges::iter_move(ranges::get<0>(detail::cidata(i)));
0236 }
0237 template<typename I1, typename S1, typename I2, typename S2>
0238 auto iter_swap(common_iterator<I1, S1> const & x,
0239 common_iterator<I2, S2> const & y)
0240 noexcept(is_nothrow_indirectly_swappable<I1, I2>::value)
0241 -> CPP_broken_friend_ret(void)(
0242 requires indirectly_swappable<I1, I2>)
0243 {
0244 return ranges::iter_swap(ranges::get<0>(detail::cidata(x)),
0245 ranges::get<0>(detail::cidata(y)));
0246 }
0247 }
0248 #endif
0249
0250
0251 template(typename I1, typename I2, typename S1, typename S2)(
0252 requires sentinel_for<S1, I2> AND sentinel_for<S2, I1> AND
0253 (!equality_comparable_with<I1, I2>))
0254 bool operator==(common_iterator<I1, S1> const & x, common_iterator<I2, S2> const & y)
0255 {
0256 return detail::cidata(x).index() == 1u ? (detail::cidata(y).index() == 1u ||
0257 ranges::get<0>(detail::cidata(y)) ==
0258 ranges::get<1>(detail::cidata(x)))
0259 : (detail::cidata(y).index() != 1u ||
0260 ranges::get<0>(detail::cidata(x)) ==
0261 ranges::get<1>(detail::cidata(y)));
0262 }
0263
0264 template(typename I1, typename I2, typename S1, typename S2)(
0265 requires sentinel_for<S1, I2> AND sentinel_for<S2, I1> AND
0266 equality_comparable_with<I1, I2>)
0267 bool operator==(common_iterator<I1, S1> const & x, common_iterator<I2, S2> const & y)
0268 {
0269 return detail::cidata(x).index() == 1u
0270 ? (detail::cidata(y).index() == 1u ||
0271 ranges::get<0>(detail::cidata(y)) ==
0272 ranges::get<1>(detail::cidata(x)))
0273 : (detail::cidata(y).index() == 1u
0274 ? ranges::get<0>(detail::cidata(x)) ==
0275 ranges::get<1>(detail::cidata(y))
0276 : ranges::get<0>(detail::cidata(x)) ==
0277 ranges::get<0>(detail::cidata(y)));
0278 }
0279
0280 template(typename I1, typename I2, typename S1, typename S2)(
0281 requires sentinel_for<S1, I2> AND sentinel_for<S2, I1>)
0282 bool operator!=(common_iterator<I1, S1> const & x, common_iterator<I2, S2> const & y)
0283 {
0284 return !(x == y);
0285 }
0286
0287 template(typename I1, typename I2, typename S1, typename S2)(
0288 requires sized_sentinel_for<I1, I2> AND sized_sentinel_for<S1, I2> AND
0289 sized_sentinel_for<S2, I1>)
0290 iter_difference_t<I2> operator-(common_iterator<I1, S1> const & x,
0291 common_iterator<I2, S2> const & y)
0292 {
0293 return detail::cidata(x).index() == 1u
0294 ? (detail::cidata(y).index() == 1u
0295 ? 0
0296 : ranges::get<1>(detail::cidata(x)) -
0297 ranges::get<0>(detail::cidata(y)))
0298 : (detail::cidata(y).index() == 1u
0299 ? ranges::get<0>(detail::cidata(x)) -
0300 ranges::get<1>(detail::cidata(y))
0301 : ranges::get<0>(detail::cidata(x)) -
0302 ranges::get<0>(detail::cidata(y)));
0303 }
0304
0305 template<typename I, typename S>
0306 struct indirectly_readable_traits<common_iterator<I, S>>
0307 : meta::if_c<
0308 (bool)indirectly_readable<I>,
0309 indirectly_readable_traits<I>,
0310 meta::nil_>
0311 {};
0312
0313
0314 namespace detail
0315 {
0316 template<typename I>
0317 auto demote_common_iter_cat(...) -> nil_;
0318 template<typename I>
0319 auto demote_common_iter_cat(long)
0320 -> with_iterator_category<std::input_iterator_tag>;
0321 template(typename I)(
0322 requires derived_from<typename std::iterator_traits<I>::iterator_category,
0323 std::forward_iterator_tag>)
0324 auto demote_common_iter_cat(int)
0325 -> with_iterator_category<std::forward_iterator_tag>;
0326
0327 template<typename I, bool = (bool)input_iterator<I>>
0328 struct common_iterator_std_traits : decltype(detail::demote_common_iter_cat<I>(0))
0329 {
0330 using difference_type = iter_difference_t<I>;
0331 using value_type = iter_value_t<I>;
0332 using reference = iter_reference_t<I>;
0333 using pointer = detail::iter_pointer_t<I>;
0334 using iterator_concept =
0335 meta::conditional_t<(bool)forward_iterator<I>, std::forward_iterator_tag,
0336 std::input_iterator_tag>;
0337 };
0338
0339 template<typename I>
0340 struct common_iterator_std_traits<I, false>
0341 {
0342 using difference_type = iter_difference_t<I>;
0343 using value_type = void;
0344 using reference = void;
0345 using pointer = void;
0346 using iterator_category = std::output_iterator_tag;
0347 };
0348
0349
0350
0351
0352 template<typename I>
0353 struct cpp17_iterator_cursor
0354 {
0355 private:
0356 friend range_access;
0357 I it_;
0358 struct mixin : basic_mixin<cpp17_iterator_cursor>
0359 {
0360 mixin() = default;
0361 #ifndef _MSC_VER
0362 using basic_mixin<cpp17_iterator_cursor>::basic_mixin;
0363 #else
0364 constexpr explicit mixin(cpp17_iterator_cursor && cur)
0365 : basic_mixin<cpp17_iterator_cursor>(
0366 static_cast<cpp17_iterator_cursor &&>(cur))
0367 {}
0368 constexpr explicit mixin(cpp17_iterator_cursor const & cur)
0369 : basic_mixin<cpp17_iterator_cursor>(cur)
0370 {}
0371 #endif
0372 explicit mixin(I it)
0373 : mixin{cpp17_iterator_cursor{std::move(it)}}
0374 {}
0375 I base() const
0376 {
0377 return this->get().it_;
0378 }
0379 };
0380
0381 public:
0382 using single_pass = meta::bool_<!forward_iterator<I>>;
0383 using difference_type = std::ptrdiff_t;
0384 using value_type = iter_value_t<I>;
0385
0386 cpp17_iterator_cursor() = default;
0387 constexpr explicit cpp17_iterator_cursor(I i)
0388 : it_(static_cast<I &&>(i))
0389 {}
0390
0391 I arrow() const
0392 {
0393 return it_;
0394 }
0395 decltype(auto) read()
0396 {
0397 return *it_;
0398 }
0399 decltype(auto) read() const
0400 {
0401 return *it_;
0402 }
0403 void next()
0404 {
0405 ++it_;
0406 }
0407 bool equal(cpp17_iterator_cursor const & that) const
0408 {
0409 return it_ == that.it_;
0410 }
0411 CPP_member
0412 auto prev()
0413 -> CPP_ret(void)(
0414 requires bidirectional_iterator<I>)
0415 {
0416 --it_;
0417 }
0418 CPP_member
0419 auto advance(std::ptrdiff_t n)
0420 -> CPP_ret(void)(
0421 requires random_access_iterator<I>)
0422 {
0423 it_ += static_cast<iter_difference_t<I>>(n);
0424 }
0425 CPP_member
0426 auto distance_to(cpp17_iterator_cursor const & that)
0427 -> CPP_ret(std::ptrdiff_t)(
0428 requires random_access_iterator<I>)
0429 {
0430 auto d = that.it_ - it_;
0431 RANGES_EXPECT(d <= PTRDIFF_MAX);
0432 return static_cast<std::ptrdiff_t>(d);
0433 }
0434 };
0435 }
0436
0437
0438 namespace cpp20
0439 {
0440 using ranges::common_iterator;
0441 }
0442
0443 }
0444
0445
0446 RANGES_DIAGNOSTIC_PUSH
0447 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
0448
0449 namespace std
0450 {
0451 template<typename I, typename S>
0452 struct iterator_traits<::ranges::common_iterator<I, S>>
0453 : ::ranges::detail::common_iterator_std_traits<I>
0454 {};
0455 }
0456
0457 RANGES_DIAGNOSTIC_POP
0458
0459
0460 #include <range/v3/detail/epilogue.hpp>
0461
0462 #endif