123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- // Copyright (C) 2019 T. Zachary Laine
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_STL_INTERFACES_REVERSE_ITERATOR_HPP
- #define BOOST_STL_INTERFACES_REVERSE_ITERATOR_HPP
- #include <boost/stl_interfaces/iterator_interface.hpp>
- namespace boost { namespace stl_interfaces { inline namespace v1 {
- namespace v1_dtl {
- template<typename Iter>
- constexpr auto ce_dist(Iter f, Iter l, std::random_access_iterator_tag)
- -> decltype(l - f)
- {
- return l - f;
- }
- template<typename Iter, typename Tag>
- constexpr auto ce_dist(Iter f, Iter l, Tag)
- -> decltype(std::distance(f, l))
- {
- decltype(std::distance(f, l)) retval = 0;
- for (; f != l; ++f) {
- ++retval;
- }
- return retval;
- }
- template<typename Iter>
- constexpr Iter ce_prev(Iter it)
- {
- return --it;
- }
- template<typename Iter, typename Offset>
- constexpr void
- ce_adv(Iter & f, Offset n, std::random_access_iterator_tag)
- {
- f += n;
- }
- template<typename Iter, typename Offset, typename Tag>
- constexpr void ce_adv(Iter & f, Offset n, Tag)
- {
- if (0 < n) {
- for (Offset i = 0; i < n; ++i) {
- ++f;
- }
- } else {
- for (Offset i = 0; i < -n; ++i) {
- --f;
- }
- }
- }
- }
- /** This type is very similar to the C++20 version of
- `std::reverse_iterator`; it is `constexpr`-, `noexcept`-, and
- proxy-friendly. */
- template<typename BidiIter>
- struct reverse_iterator
- : iterator_interface<
- reverse_iterator<BidiIter>,
- #if 201703L < __cplusplus && defined(__cpp_lib_ranges)
- typename v2::detail::iter_concept_t<BidiIter>,
- #else
- typename std::iterator_traits<BidiIter>::iterator_category,
- #endif
- typename std::iterator_traits<BidiIter>::value_type,
- typename std::iterator_traits<BidiIter>::reference,
- typename std::iterator_traits<BidiIter>::pointer,
- typename std::iterator_traits<BidiIter>::difference_type>
- {
- constexpr reverse_iterator() noexcept(noexcept(BidiIter())) : it_() {}
- constexpr reverse_iterator(BidiIter it) noexcept(
- noexcept(BidiIter(it))) :
- it_(it)
- {}
- template<
- typename BidiIter2,
- typename E = std::enable_if_t<
- std::is_convertible<BidiIter2, BidiIter>::value>>
- reverse_iterator(reverse_iterator<BidiIter2> const & it) : it_(it.it_)
- {}
- friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR auto
- operator-(reverse_iterator lhs, reverse_iterator rhs) noexcept(
- noexcept(v1_dtl::ce_dist(
- lhs.it_,
- rhs.it_,
- typename std::iterator_traits<BidiIter>::iterator_category{})))
- {
- return -v1_dtl::ce_dist(
- rhs.it_,
- lhs.it_,
- typename std::iterator_traits<BidiIter>::iterator_category{});
- }
- constexpr typename std::iterator_traits<BidiIter>::reference
- operator*() const noexcept(
- noexcept(std::prev(v1_dtl::ce_prev(std::declval<BidiIter &>()))))
- {
- return *v1_dtl::ce_prev(it_);
- }
- constexpr reverse_iterator & operator+=(
- typename std::iterator_traits<BidiIter>::difference_type
- n) noexcept(noexcept(v1_dtl::
- ce_adv(
- std::declval<BidiIter &>(),
- -n,
- typename std::iterator_traits<
- BidiIter>::
- iterator_category{})))
- {
- v1_dtl::ce_adv(
- it_,
- -n,
- typename std::iterator_traits<BidiIter>::iterator_category{});
- return *this;
- }
- constexpr BidiIter base() const noexcept { return it_; }
- private:
- friend access;
- constexpr BidiIter & base_reference() noexcept { return it_; }
- constexpr BidiIter const & base_reference() const noexcept
- {
- return it_;
- }
- template<typename BidiIter2>
- friend struct reverse_iterator;
- BidiIter it_;
- };
- template<typename BidiIter>
- constexpr auto operator==(
- reverse_iterator<BidiIter> lhs,
- reverse_iterator<BidiIter>
- rhs) noexcept(noexcept(lhs.base() == rhs.base()))
- -> decltype(rhs.base() == lhs.base())
- {
- return lhs.base() == rhs.base();
- }
- template<typename BidiIter1, typename BidiIter2>
- constexpr auto operator==(
- reverse_iterator<BidiIter1> lhs,
- reverse_iterator<BidiIter2>
- rhs) noexcept(noexcept(lhs.base() == rhs.base()))
- -> decltype(rhs.base() == lhs.base())
- {
- return lhs.base() == rhs.base();
- }
- /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
- `Bidiiter`. */
- template<typename BidiIter>
- auto make_reverse_iterator(BidiIter it)
- {
- return reverse_iterator<BidiIter>(it);
- }
- }}}
- #if 201703L < __cplusplus && defined(__cpp_lib_concepts) || \
- defined(BOOST_STL_INTERFACES_DOXYGEN)
- namespace boost { namespace stl_interfaces { namespace v2 {
- /** A template alias for `std::reverse_iterator`. This only exists to
- make migration from Boost.STLInterfaces to C++20 easier; switch to the
- one in `std` as soon as you can. */
- template<typename BidiIter>
- using reverse_iterator = std::reverse_iterator<BidiIter>;
- /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
- `Bidiiter`. This only exists to make migration from
- Boost.STLInterfaces to C++20 easier; switch to the one in `std` as
- soon as you can. */
- template<typename BidiIter>
- auto make_reverse_iterator(BidiIter it)
- {
- return reverse_iterator<BidiIter>(it);
- }
- }}}
- #endif
- #endif
|