Warning, file /include/range/v3/iterator/move_iterators.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef RANGES_V3_ITERATOR_MOVE_ITERATORS_HPP
0014 #define RANGES_V3_ITERATOR_MOVE_ITERATORS_HPP
0015
0016 #include <cstddef>
0017 #include <utility>
0018
0019 #include <range/v3/range_fwd.hpp>
0020
0021 #include <range/v3/iterator/basic_iterator.hpp>
0022 #include <range/v3/iterator/concepts.hpp>
0023 #include <range/v3/iterator/traits.hpp>
0024
0025 #include <range/v3/detail/prologue.hpp>
0026
0027 namespace ranges
0028 {
0029
0030
0031 template<typename I>
0032 struct move_iterator
0033 {
0034 private:
0035 CPP_assert(input_iterator<I>);
0036 I current_ = I{};
0037
0038 public:
0039 using iterator_type = I;
0040 using difference_type = iter_difference_t<I>;
0041 using value_type = iter_value_t<I>;
0042 using iterator_category = std::input_iterator_tag;
0043 using reference = iter_rvalue_reference_t<I>;
0044
0045 constexpr move_iterator() = default;
0046 explicit move_iterator(I i)
0047 : current_(i)
0048 {}
0049 template(typename O)(
0050 requires convertible_to<O, I>)
0051 move_iterator(move_iterator<O> const & i)
0052 : current_(i.base())
0053 {}
0054 template(typename O)(
0055 requires convertible_to<O, I>)
0056 move_iterator & operator=(move_iterator<O> const & i)
0057 {
0058 current_ = i.base();
0059 return *this;
0060 }
0061 I base() const
0062 {
0063 return current_;
0064 }
0065
0066 auto CPP_auto_fun(operator*)()(const)
0067 (
0068 return iter_move(current_)
0069 )
0070
0071 move_iterator &
0072 operator++()
0073 {
0074 ++current_;
0075 return *this;
0076 }
0077 CPP_member
0078 auto operator++(int)
0079 -> CPP_ret(void)(
0080 requires (!forward_iterator<I>))
0081 {
0082 ++current_;
0083 }
0084 CPP_member
0085 auto operator++(int)
0086 -> CPP_ret(move_iterator)(
0087 requires forward_iterator<I>)
0088 {
0089 return move_iterator(current_++);
0090 }
0091 CPP_member
0092 auto operator--()
0093 -> CPP_ret(move_iterator &)(
0094 requires forward_iterator<I>)
0095 {
0096 --current_;
0097 return *this;
0098 }
0099 CPP_member
0100 auto operator--(int)
0101 -> CPP_ret(move_iterator)(
0102 requires bidirectional_iterator<I>)
0103 {
0104 return move_iterator(current_--);
0105 }
0106 CPP_member
0107 auto operator+(difference_type n) const
0108 -> CPP_ret(move_iterator)(
0109 requires random_access_iterator<I>)
0110 {
0111 return move_iterator(current_ + n);
0112 }
0113 CPP_member
0114 auto operator+=(difference_type n)
0115 -> CPP_ret(move_iterator &)(
0116 requires random_access_iterator<I>)
0117 {
0118 current_ += n;
0119 return *this;
0120 }
0121 CPP_member
0122 auto operator-(difference_type n) const
0123 -> CPP_ret(move_iterator)(
0124 requires random_access_iterator<I>)
0125 {
0126 return move_iterator(current_ - n);
0127 }
0128 CPP_member
0129 auto operator-=(difference_type n)
0130 -> CPP_ret(move_iterator &)(
0131 requires random_access_iterator<I>)
0132 {
0133 current_ -= n;
0134 return *this;
0135 }
0136 CPP_member
0137 auto operator[](difference_type n) const
0138 -> CPP_ret(reference)(
0139 requires random_access_iterator<I>)
0140 {
0141 return iter_move(current_ + n);
0142 }
0143
0144 template<typename I2>
0145 friend auto operator==(move_iterator const & x, move_iterator<I2> const & y)
0146 -> CPP_broken_friend_ret(bool)(
0147 requires equality_comparable_with<I, I2>)
0148 {
0149 return x.base() == y.base();
0150 }
0151 template<typename I2>
0152 friend auto operator!=(move_iterator const & x, move_iterator<I2> const & y)
0153 -> CPP_broken_friend_ret(bool)(
0154 requires equality_comparable_with<I, I2>)
0155 {
0156 return !(x == y);
0157 }
0158 template<typename I2>
0159 friend auto operator<(move_iterator const & x, move_iterator<I2> const & y)
0160 -> CPP_broken_friend_ret(bool)(
0161 requires totally_ordered_with<I, I2>)
0162 {
0163 return x.base() < y.base();
0164 }
0165 template<typename I2>
0166 friend auto operator<=(move_iterator const & x, move_iterator<I2> const & y)
0167 -> CPP_broken_friend_ret(bool)(
0168 requires totally_ordered_with<I, I2>)
0169 {
0170 return !(y < x);
0171 }
0172 template<typename I2>
0173 friend auto operator>(move_iterator const & x, move_iterator<I2> const & y)
0174 -> CPP_broken_friend_ret(bool)(
0175 requires totally_ordered_with<I, I2>)
0176 {
0177 return y < x;
0178 }
0179 template<typename I2>
0180 friend auto operator>=(move_iterator const & x, move_iterator<I2> const & y)
0181 -> CPP_broken_friend_ret(bool)(
0182 requires totally_ordered_with<I, I2>)
0183 {
0184 return !(x < y);
0185 }
0186
0187 template<typename I2>
0188 friend auto operator-(move_iterator const & x, move_iterator<I2> const & y)
0189 -> CPP_broken_friend_ret(iter_difference_t<I2>)(
0190 requires sized_sentinel_for<I, I2>)
0191 {
0192 return x.base() - y.base();
0193 }
0194 CPP_broken_friend_member
0195 friend auto operator+(iter_difference_t<I> n,
0196 move_iterator const & x)
0197 -> CPP_broken_friend_ret(move_iterator)(
0198 requires random_access_iterator<I>)
0199 {
0200 return x + n;
0201 }
0202 };
0203
0204 struct make_move_iterator_fn
0205 {
0206 template(typename I)(
0207 requires input_iterator<I>)
0208 constexpr move_iterator<I> operator()(I it) const
0209 {
0210 return move_iterator<I>{detail::move(it)};
0211 }
0212 };
0213
0214 RANGES_INLINE_VARIABLE(make_move_iterator_fn, make_move_iterator)
0215
0216 template<typename S>
0217 struct move_sentinel
0218 {
0219 private:
0220 S sent_;
0221
0222 public:
0223 constexpr move_sentinel()
0224 : sent_{}
0225 {}
0226 constexpr explicit move_sentinel(S s)
0227 : sent_(detail::move(s))
0228 {}
0229 template(typename OS)(
0230 requires convertible_to<OS, S>)
0231 constexpr explicit move_sentinel(move_sentinel<OS> const & that)
0232 : sent_(that.base())
0233 {}
0234 template(typename OS)(
0235 requires convertible_to<OS, S>)
0236 move_sentinel & operator=(move_sentinel<OS> const & that)
0237 {
0238 sent_ = that.base();
0239 return *this;
0240 }
0241 S base() const
0242 {
0243 return sent_;
0244 }
0245
0246 template<typename I>
0247 friend auto operator==(move_iterator<I> const & i, move_sentinel const & s)
0248 -> CPP_broken_friend_ret(bool)(
0249 requires sentinel_for<S, I>)
0250 {
0251 return i.base() == s.base();
0252 }
0253 template<typename I>
0254 friend auto operator==(move_sentinel const & s, move_iterator<I> const & i)
0255 -> CPP_broken_friend_ret(bool)(
0256 requires sentinel_for<S, I>)
0257 {
0258 return s.base() == i.base();
0259 }
0260 template<typename I>
0261 friend auto operator!=(move_iterator<I> const & i, move_sentinel const & s)
0262 -> CPP_broken_friend_ret(bool)(
0263 requires sentinel_for<S, I>)
0264 {
0265 return i.base() != s.base();
0266 }
0267 template<typename I>
0268 friend auto operator!=(move_sentinel const & s, move_iterator<I> const & i)
0269 -> CPP_broken_friend_ret(bool)(
0270 requires sentinel_for<S, I>)
0271 {
0272 return s.base() != i.base();
0273 }
0274 };
0275
0276 struct make_move_sentinel_fn
0277 {
0278 template(typename I)(
0279 requires input_iterator<I>)
0280 constexpr move_iterator<I> operator()(I i) const
0281 {
0282 return move_iterator<I>{detail::move(i)};
0283 }
0284
0285 template(typename S)(
0286 requires semiregular<S> AND (!input_iterator<S>))
0287 constexpr move_sentinel<S> operator()(S s) const
0288 {
0289 return move_sentinel<S>{detail::move(s)};
0290 }
0291 };
0292
0293 RANGES_INLINE_VARIABLE(make_move_sentinel_fn, make_move_sentinel)
0294
0295
0296 namespace detail
0297 {
0298 template<typename I, bool IsReadable>
0299 struct move_into_cursor_types_
0300 {};
0301
0302 template<typename I>
0303 struct move_into_cursor_types_<I, true>
0304 {
0305 using value_type = iter_value_t<I>;
0306 using single_pass = meta::bool_<(bool)single_pass_iterator_<I>>;
0307 };
0308
0309 template<typename I>
0310 using move_into_cursor_types =
0311 move_into_cursor_types_<I, (bool)indirectly_readable<I>>;
0312
0313 template<typename I>
0314 struct move_into_cursor : move_into_cursor_types<I>
0315 {
0316 private:
0317 friend range_access;
0318 struct mixin : basic_mixin<move_into_cursor>
0319 {
0320 mixin() = default;
0321 #ifndef _MSC_VER
0322 using basic_mixin<move_into_cursor>::basic_mixin;
0323 #else
0324 constexpr explicit mixin(move_into_cursor && cur)
0325 : basic_mixin<move_into_cursor>(static_cast<move_into_cursor &&>(cur))
0326 {}
0327 constexpr explicit mixin(move_into_cursor const & cur)
0328 : basic_mixin<move_into_cursor>(cur)
0329 {}
0330 #endif
0331 explicit mixin(I it)
0332 : mixin{move_into_cursor{std::move(it)}}
0333 {}
0334 I base() const
0335 {
0336 return this->get().it_;
0337 }
0338 };
0339
0340 I it_ = I();
0341
0342 explicit move_into_cursor(I it)
0343 : it_(std::move(it))
0344 {}
0345 void next()
0346 {
0347 ++it_;
0348 }
0349 template(typename T)(
0350 requires indirectly_writable<I, aux::move_t<T>>)
0351 void write(T && t) noexcept(noexcept(*it_ = std::move(t)))
0352 {
0353 *it_ = std::move(t);
0354 }
0355 template(typename T)(
0356 requires indirectly_writable<I, aux::move_t<T>>)
0357 void write(T && t) const noexcept(noexcept(*it_ = std::move(t)))
0358 {
0359 *it_ = std::move(t);
0360 }
0361 CPP_member
0362 auto read() const noexcept(noexcept(*std::declval<I const &>()))
0363 -> CPP_ret(iter_reference_t<I>)(
0364 requires indirectly_readable<I>)
0365 {
0366 return *it_;
0367 }
0368 CPP_member
0369 auto equal(move_into_cursor const & that) const
0370 -> CPP_ret(bool)(
0371 requires input_iterator<I>)
0372 {
0373 return it_ == that.it_;
0374 }
0375 CPP_member
0376 auto prev()
0377 -> CPP_ret(void)(
0378 requires bidirectional_iterator<I>)
0379 {
0380 --it_;
0381 }
0382 CPP_member
0383 auto advance(iter_difference_t<I> n)
0384 -> CPP_ret(void)(
0385 requires random_access_iterator<I>)
0386 {
0387 it_ += n;
0388 }
0389 CPP_member
0390 auto distance_to(move_into_cursor const & that) const
0391 -> CPP_ret(iter_difference_t<I>)(
0392 requires sized_sentinel_for<I, I>)
0393 {
0394 return that.it_ - it_;
0395 }
0396 template(typename II = I const)(
0397 requires same_as<I const, II> AND indirectly_readable<II>)
0398 constexpr iter_rvalue_reference_t<II> move() const
0399 noexcept(has_nothrow_iter_move_v<II>)
0400 {
0401 return iter_move(it_);
0402 }
0403
0404 public:
0405 constexpr move_into_cursor() = default;
0406 };
0407 }
0408
0409
0410 struct move_into_fn
0411 {
0412 template<typename I>
0413 constexpr move_into_iterator<I> operator()(I it) const
0414 {
0415 return move_into_iterator<I>{std::move(it)};
0416 }
0417 };
0418
0419
0420 RANGES_INLINE_VARIABLE(move_into_fn, move_into)
0421
0422 namespace cpp20
0423 {
0424 using ranges::make_move_iterator;
0425 using ranges::move_iterator;
0426 using ranges::move_sentinel;
0427 }
0428
0429 }
0430
0431
0432 RANGES_DIAGNOSTIC_PUSH
0433 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
0434
0435 namespace std
0436 {
0437 template<typename I>
0438 struct iterator_traits<::ranges::move_iterator<I>>
0439 {
0440 using iterator_category = std::input_iterator_tag;
0441 using difference_type = typename ::ranges::move_iterator<I>::difference_type;
0442 using value_type = typename ::ranges::move_iterator<I>::value_type;
0443 using reference = typename ::ranges::move_iterator<I>::reference;
0444 using pointer = meta::_t<std::add_pointer<reference>>;
0445 };
0446 }
0447
0448 RANGES_DIAGNOSTIC_POP
0449
0450
0451 #include <range/v3/detail/epilogue.hpp>
0452
0453 #endif