Back to home page

EIC code displayed by LXR

 
 

    


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 /// \file
0002 // Range v3 library
0003 //
0004 //  Copyright Eric Niebler 2014-present
0005 //
0006 //  Use, modification and distribution is subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Project home: https://github.com/ericniebler/range-v3
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     /// \addtogroup group-iterator
0032     /// @{
0033 
0034     /// \cond
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     } // namespace _counted_iterator_
0069     /// \endcond
0070 
0071     template<typename I>
0072         // requires input_or_output_iterator<I>
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  // ^^^ workaround ^^^ / vvv no workaround vvv
0164         CPP_member
0165         constexpr auto operator++(int) //
0166             -> CPP_ret(decltype(std::declval<I &>()++))(
0167                 requires (!forward_iterator<I>))
0168 #endif // RANGES_WORKAROUND_MSVC_677925
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     /// \cond
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     } // namespace _counted_iterator_
0300 #endif
0301     /// endcond
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 } // namespace ranges
0436 
0437 /// \cond
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     } // namespace _counted_iterator_
0459 } // namespace ranges
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 } // namespace std
0468 /// \endcond
0469 
0470 #include <range/v3/detail/epilogue.hpp>
0471 
0472 #endif