Warning, file /include/range/v3/iterator/counted_iterator.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_COUNTED_ITERATOR_HPP
0014 #define RANGES_V3_ITERATOR_COUNTED_ITERATOR_HPP
0015
0016 #include <utility>
0017
0018 #include <meta/meta.hpp>
0019
0020 #include <range/v3/range_fwd.hpp>
0021
0022 #include <range/v3/iterator/concepts.hpp>
0023 #include <range/v3/iterator/default_sentinel.hpp>
0024 #include <range/v3/iterator/operations.hpp>
0025 #include <range/v3/iterator/traits.hpp>
0026
0027 #include <range/v3/detail/prologue.hpp>
0028
0029 namespace ranges
0030 {
0031
0032
0033
0034
0035 namespace _counted_iterator_
0036 {
0037 struct access
0038 {
0039 template<typename I>
0040 static constexpr iter_difference_t<counted_iterator<I>> & count(
0041 counted_iterator<I> & ci) noexcept
0042 {
0043 return ci.cnt_;
0044 }
0045
0046 template<typename I>
0047 static constexpr I & current(counted_iterator<I> & ci) noexcept
0048 {
0049 return ci.current_;
0050 }
0051
0052 template<typename I>
0053 static constexpr I const & current(counted_iterator<I> const & ci) noexcept
0054 {
0055 return ci.current_;
0056 }
0057 };
0058
0059 template<bool>
0060 struct contiguous_iterator_concept_base
0061 {};
0062
0063 template<>
0064 struct contiguous_iterator_concept_base<true>
0065 {
0066 using iterator_concept = ranges::contiguous_iterator_tag;
0067 };
0068 }
0069
0070
0071 template<typename I>
0072
0073 struct counted_iterator
0074 : _counted_iterator_::contiguous_iterator_concept_base<(bool)contiguous_iterator<I>>
0075 {
0076 private:
0077 friend advance_fn;
0078 CPP_assert(input_or_output_iterator<I>);
0079 friend _counted_iterator_::access;
0080
0081 I current_{};
0082 iter_difference_t<I> cnt_{0};
0083
0084 constexpr void post_increment_(std::true_type)
0085 {
0086 CPP_assert(std::is_void<decltype(current_++)>());
0087 ++current_;
0088 --cnt_;
0089 }
0090 constexpr auto post_increment_(std::false_type) -> decltype(current_++)
0091 {
0092 CPP_assert(!std::is_void<decltype(current_++)>());
0093 auto && tmp = current_++;
0094 --cnt_;
0095 return static_cast<decltype(tmp) &&>(tmp);
0096 }
0097
0098 public:
0099 using iterator_type = I;
0100 using difference_type = iter_difference_t<I>;
0101
0102 counted_iterator() = default;
0103
0104 constexpr counted_iterator(I x, iter_difference_t<I> n)
0105 : current_(std::move(x))
0106 , cnt_(n)
0107 {
0108 RANGES_EXPECT(n >= 0);
0109 }
0110
0111 template(typename I2)(
0112 requires convertible_to<I2, I>)
0113 constexpr counted_iterator(counted_iterator<I2> const & i)
0114 : current_(_counted_iterator_::access::current(i))
0115 , cnt_(i.count())
0116 {}
0117
0118 template(typename I2)(
0119 requires convertible_to<I2, I>)
0120 constexpr counted_iterator & operator=(counted_iterator<I2> const & i)
0121 {
0122 current_ = _counted_iterator_::access::current(i);
0123 cnt_ = i.count();
0124 }
0125
0126 constexpr I base() const
0127 {
0128 return current_;
0129 }
0130
0131 constexpr iter_difference_t<I> count() const
0132 {
0133 return cnt_;
0134 }
0135
0136 constexpr iter_reference_t<I> operator*() noexcept(
0137 noexcept(iter_reference_t<I>(*current_)))
0138 {
0139 RANGES_EXPECT(cnt_ > 0);
0140 return *current_;
0141 }
0142 template(typename I2 = I)(
0143 requires indirectly_readable<I2 const>)
0144 constexpr iter_reference_t<I2> operator*() const
0145 noexcept(noexcept(iter_reference_t<I>(*current_)))
0146 {
0147 RANGES_EXPECT(cnt_ > 0);
0148 return *current_;
0149 }
0150
0151 constexpr counted_iterator & operator++()
0152 {
0153 RANGES_EXPECT(cnt_ > 0);
0154 ++current_;
0155 --cnt_;
0156 return *this;
0157 }
0158
0159 #ifdef RANGES_WORKAROUND_MSVC_677925
0160 template(typename I2 = I)(
0161 requires (!forward_iterator<I2>))
0162 constexpr auto operator++(int) -> decltype(std::declval<I2 &>()++)
0163 #else
0164 CPP_member
0165 constexpr auto operator++(int)
0166 -> CPP_ret(decltype(std::declval<I &>()++))(
0167 requires (!forward_iterator<I>))
0168 #endif
0169 {
0170 RANGES_EXPECT(cnt_ > 0);
0171 return post_increment_(std::is_void<decltype(current_++)>());
0172 }
0173
0174 CPP_member
0175 constexpr auto operator++(int)
0176 -> CPP_ret(counted_iterator)(
0177 requires forward_iterator<I>)
0178 {
0179 auto tmp(*this);
0180 ++*this;
0181 return tmp;
0182 }
0183
0184 CPP_member
0185 constexpr auto operator--()
0186 -> CPP_ret(counted_iterator &)(
0187 requires bidirectional_iterator<I>)
0188 {
0189 --current_;
0190 ++cnt_;
0191 return *this;
0192 }
0193
0194 CPP_member
0195 constexpr auto operator--(int)
0196 -> CPP_ret(counted_iterator)(
0197 requires bidirectional_iterator<I>)
0198 {
0199 auto tmp(*this);
0200 --*this;
0201 return tmp;
0202 }
0203
0204 CPP_member
0205 constexpr auto operator+=(difference_type n)
0206 -> CPP_ret(counted_iterator &)(
0207 requires random_access_iterator<I>)
0208 {
0209 RANGES_EXPECT(cnt_ >= n);
0210 current_ += n;
0211 cnt_ -= n;
0212 return *this;
0213 }
0214
0215 CPP_member
0216 constexpr auto operator+(difference_type n) const
0217 -> CPP_ret(counted_iterator)(
0218 requires random_access_iterator<I>)
0219 {
0220 auto tmp(*this);
0221 tmp += n;
0222 return tmp;
0223 }
0224
0225 CPP_member
0226 constexpr auto operator-=(difference_type n)
0227 -> CPP_ret(counted_iterator &)(
0228 requires random_access_iterator<I>)
0229 {
0230 RANGES_EXPECT(cnt_ >= -n);
0231 current_ -= n;
0232 cnt_ += n;
0233 return *this;
0234 }
0235
0236 CPP_member
0237 constexpr auto operator-(difference_type n) const
0238 -> CPP_ret(counted_iterator)(
0239 requires random_access_iterator<I>)
0240 {
0241 auto tmp(*this);
0242 tmp -= n;
0243 return tmp;
0244 }
0245
0246 CPP_member
0247 constexpr auto operator[](difference_type n) const
0248 -> CPP_ret(iter_reference_t<I>)(
0249 requires random_access_iterator<I>)
0250 {
0251 RANGES_EXPECT(cnt_ >= n);
0252 return current_[n];
0253 }
0254
0255 #if !RANGES_BROKEN_CPO_LOOKUP
0256 CPP_broken_friend_member
0257 friend constexpr auto iter_move(counted_iterator const & i)
0258 noexcept(detail::has_nothrow_iter_move_v<I>)
0259 -> CPP_broken_friend_ret(iter_rvalue_reference_t<I>)(
0260 requires input_iterator<I>)
0261 {
0262 return ranges::iter_move(i.current_);
0263 }
0264 template<typename I2, typename S2>
0265 friend constexpr auto iter_swap(counted_iterator const & x,
0266 counted_iterator<I2> const & y)
0267 noexcept(is_nothrow_indirectly_swappable<I, I2>::value)
0268 -> CPP_broken_friend_ret(void)(
0269 requires indirectly_swappable<I2, I>)
0270 {
0271 return ranges::iter_swap(x.current_, _counted_iterator_::access::current(y));
0272 }
0273 #endif
0274 };
0275
0276
0277 #if RANGES_BROKEN_CPO_LOOKUP
0278 namespace _counted_iterator_
0279 {
0280 template<typename I>
0281 constexpr auto iter_move(counted_iterator<I> const & i) noexcept(
0282 detail::has_nothrow_iter_move_v<I>)
0283 -> CPP_broken_friend_ret(iter_rvalue_reference_t<I>)(
0284 requires input_iterator<I>)
0285 {
0286 return ranges::iter_move(_counted_iterator_::access::current(i));
0287 }
0288 template<typename I1, typename I2>
0289 constexpr auto iter_swap(
0290 counted_iterator<I1> const & x,
0291 counted_iterator<I2> const &
0292 y) noexcept(is_nothrow_indirectly_swappable<I1, I2>::value)
0293 -> CPP_broken_friend_ret(void)(
0294 requires indirectly_swappable<I2, I1>)
0295 {
0296 return ranges::iter_swap(_counted_iterator_::access::current(x),
0297 _counted_iterator_::access::current(y));
0298 }
0299 }
0300 #endif
0301
0302
0303 template(typename I1, typename I2)(
0304 requires common_with<I1, I2>)
0305 constexpr bool operator==(counted_iterator<I1> const & x,
0306 counted_iterator<I2> const & y)
0307 {
0308 return x.count() == y.count();
0309 }
0310
0311 template<typename I>
0312 constexpr bool operator==(counted_iterator<I> const & x, default_sentinel_t)
0313 {
0314 return x.count() == 0;
0315 }
0316
0317 template<typename I>
0318 constexpr bool operator==(default_sentinel_t, counted_iterator<I> const & x)
0319 {
0320 return x.count() == 0;
0321 }
0322
0323 template(typename I1, typename I2)(
0324 requires common_with<I1, I2>)
0325 constexpr bool operator!=(counted_iterator<I1> const & x,
0326 counted_iterator<I2> const & y)
0327 {
0328 return !(x == y);
0329 }
0330
0331 template<typename I>
0332 constexpr bool operator!=(counted_iterator<I> const & x, default_sentinel_t y)
0333 {
0334 return !(x == y);
0335 }
0336
0337 template<typename I>
0338 constexpr bool operator!=(default_sentinel_t x, counted_iterator<I> const & y)
0339 {
0340 return !(x == y);
0341 }
0342
0343 template(typename I1, typename I2)(
0344 requires common_with<I1, I2>)
0345 constexpr bool operator<(counted_iterator<I1> const & x,
0346 counted_iterator<I2> const & y)
0347 {
0348 return y.count() < x.count();
0349 }
0350
0351 template(typename I1, typename I2)(
0352 requires common_with<I1, I2>)
0353 constexpr bool operator<=(counted_iterator<I1> const & x,
0354 counted_iterator<I2> const & y)
0355 {
0356 return !(y < x);
0357 }
0358
0359 template(typename I1, typename I2)(
0360 requires common_with<I1, I2>)
0361 constexpr bool operator>(counted_iterator<I1> const & x,
0362 counted_iterator<I2> const & y)
0363 {
0364 return y < x;
0365 }
0366
0367 template(typename I1, typename I2)(
0368 requires common_with<I1, I2>)
0369 constexpr bool operator>=(counted_iterator<I1> const & x,
0370 counted_iterator<I2> const & y)
0371 {
0372 return !(x < y);
0373 }
0374
0375 template(typename I1, typename I2)(
0376 requires common_with<I1, I2>)
0377 constexpr iter_difference_t<I2> operator-(counted_iterator<I1> const & x,
0378 counted_iterator<I2> const & y)
0379 {
0380 return y.count() - x.count();
0381 }
0382
0383 template<typename I>
0384 constexpr iter_difference_t<I> operator-(counted_iterator<I> const & x,
0385 default_sentinel_t)
0386 {
0387 return -x.count();
0388 }
0389
0390 template<typename I>
0391 constexpr iter_difference_t<I> operator-(default_sentinel_t,
0392 counted_iterator<I> const & y)
0393 {
0394 return y.count();
0395 }
0396
0397 template(typename I)(
0398 requires random_access_iterator<I>)
0399 constexpr counted_iterator<I> operator+(iter_difference_t<I> n,
0400 counted_iterator<I> const & x)
0401 {
0402 return x + n;
0403 }
0404
0405 template(typename I)(
0406 requires input_or_output_iterator<I>)
0407 constexpr counted_iterator<I> make_counted_iterator(I i, iter_difference_t<I> n)
0408 {
0409 return {std::move(i), n};
0410 }
0411
0412 template<typename I>
0413 struct indirectly_readable_traits<counted_iterator<I>>
0414 : meta::conditional_t<
0415 (bool)indirectly_readable<I>,
0416 indirectly_readable_traits<I>,
0417 meta::nil_>
0418 {};
0419
0420 CPP_template_def(typename I)(
0421 requires input_or_output_iterator<I>)
0422 constexpr void advance_fn::operator()(counted_iterator<I> & i,
0423 iter_difference_t<I> n) const
0424 {
0425 RANGES_EXPECT(n <= i.cnt_);
0426 advance(i.current_, n);
0427 i.cnt_ -= n;
0428 }
0429
0430 namespace cpp20
0431 {
0432 using ranges::counted_iterator;
0433 }
0434
0435 }
0436
0437
0438 namespace ranges
0439 {
0440 namespace _counted_iterator_
0441 {
0442 template<typename I, typename = void>
0443 struct iterator_traits_
0444 {
0445 using difference_type = iter_difference_t<I>;
0446 using value_type = void;
0447 using reference = void;
0448 using pointer = void;
0449 using iterator_category = std::output_iterator_tag;
0450 };
0451
0452 template<typename I>
0453 struct iterator_traits_<I, meta::if_c<input_iterator<I>>>
0454 : std::iterator_traits<I>
0455 {
0456 using pointer = void;
0457 };
0458 }
0459 }
0460
0461 namespace std
0462 {
0463 template<typename I>
0464 struct iterator_traits<::ranges::counted_iterator<I>>
0465 : ::ranges::_counted_iterator_::iterator_traits_<I>
0466 {};
0467 }
0468
0469
0470 #include <range/v3/detail/epilogue.hpp>
0471
0472 #endif