/// \file // Range v3 library // // Copyright Eric Niebler 2014-present // // Use, modification and distribution is subject to 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) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_VIEW_REVERSE_HPP #define RANGES_V3_VIEW_REVERSE_HPP #include <iterator> #include <utility> #include <meta/meta.hpp> #include <range/v3/range_fwd.hpp> #include <range/v3/iterator/operations.hpp> #include <range/v3/iterator/reverse_iterator.hpp> #include <range/v3/range/access.hpp> #include <range/v3/range/primitives.hpp> #include <range/v3/range/traits.hpp> #include <range/v3/utility/box.hpp> #include <range/v3/utility/get.hpp> #include <range/v3/utility/optional.hpp> #include <range/v3/utility/static_const.hpp> #include <range/v3/view/adaptor.hpp> #include <range/v3/view/all.hpp> #include <range/v3/view/view.hpp> namespace ranges { /// \addtogroup group-views /// @{ template<typename Rng> struct RANGES_EMPTY_BASES reverse_view : view_interface<reverse_view<Rng>, range_cardinality<Rng>::value> , private detail::non_propagating_cache<iterator_t<Rng>, reverse_view<Rng>, !common_range<Rng>> { private: CPP_assert(bidirectional_range<Rng>); Rng rng_; constexpr reverse_iterator<iterator_t<Rng>> begin_(std::true_type) { return make_reverse_iterator(ranges::end(rng_)); } constexpr reverse_iterator<iterator_t<Rng>> begin_(std::false_type) { using cache_t = detail::non_propagating_cache<iterator_t<Rng>, reverse_view<Rng>>; auto & end_ = static_cast<cache_t &>(*this); if(!end_) end_ = ranges::next(ranges::begin(rng_), ranges::end(rng_)); return make_reverse_iterator(*end_); } public: reverse_view() = default; explicit constexpr reverse_view(Rng rng) : rng_(detail::move(rng)) {} Rng base() const { return rng_; } constexpr reverse_iterator<iterator_t<Rng>> begin() { return begin_(meta::bool_<(bool)common_range<Rng>>{}); } template<bool Const = true> constexpr auto begin() const -> CPP_ret(reverse_iterator<iterator_t<meta::const_if_c<Const, Rng>>>)( // requires Const && common_range<meta::const_if_c<Const, Rng>>) { return make_reverse_iterator(ranges::end(rng_)); } constexpr reverse_iterator<iterator_t<Rng>> end() { return make_reverse_iterator(ranges::begin(rng_)); } template<bool Const = true> constexpr auto end() const -> CPP_ret(reverse_iterator<iterator_t<meta::const_if_c<Const, Rng>>>)( // requires Const && common_range<meta::const_if_c<Const, Rng>>) { return make_reverse_iterator(ranges::begin(rng_)); } CPP_member constexpr auto CPP_fun(size)()(requires sized_range<Rng>) { return ranges::size(rng_); } CPP_member constexpr auto CPP_fun(size)()(const requires sized_range<Rng const>) { return ranges::size(rng_); } }; template<typename Rng> struct reverse_view<reverse_view<Rng>> : Rng { CPP_assert(bidirectional_range<Rng>); CPP_assert( same_as<detail::decay_t<decltype(std::declval<reverse_view<Rng>>().base())>, Rng>); reverse_view() = default; explicit constexpr reverse_view(reverse_view<Rng> rng) : Rng(rng.base()) {} constexpr reverse_view<Rng> base() const { return reverse_view<Rng>{*this}; } }; #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17 template<typename Rng> reverse_view(Rng &&)->reverse_view<views::all_t<Rng>>; template<typename Rng> reverse_view(reverse_view<Rng>)->reverse_view<reverse_view<Rng>>; #endif namespace views { struct reverse_fn { template<typename Rng> constexpr auto operator()(Rng && rng) const -> CPP_ret(reverse_view<all_t<Rng>>)( // requires viewable_range<Rng> && bidirectional_range<Rng>) { return reverse_view<all_t<Rng>>{all(static_cast<Rng &&>(rng))}; } }; /// \relates reverse_fn /// \ingroup group-views RANGES_INLINE_VARIABLE(view<reverse_fn>, reverse) } // namespace views namespace cpp20 { namespace views { using ranges::views::reverse; } CPP_template(typename Rng)( // requires view_<Rng> && bidirectional_range<Rng>) // using reverse_view = ranges::reverse_view<Rng>; } // namespace cpp20 /// @} } // namespace ranges #include <range/v3/detail/satisfy_boost_range.hpp> RANGES_SATISFY_BOOST_RANGE(::ranges::reverse_view) #endif