Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:09:54

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_VIEW_CACHE1_HPP
0014 #define RANGES_V3_VIEW_CACHE1_HPP
0015 
0016 #include <range/v3/range_fwd.hpp>
0017 
0018 #include <range/v3/detail/range_access.hpp>
0019 #include <range/v3/iterator/concepts.hpp>
0020 #include <range/v3/range/access.hpp>
0021 #include <range/v3/range/concepts.hpp>
0022 #include <range/v3/range/primitives.hpp>
0023 #include <range/v3/range/traits.hpp>
0024 #include <range/v3/utility/optional.hpp>
0025 #include <range/v3/view/adaptor.hpp>
0026 #include <range/v3/view/all.hpp>
0027 
0028 #include <range/v3/detail/prologue.hpp>
0029 
0030 namespace ranges
0031 {
0032     /// \addtogroup group-views
0033     /// @{
0034     template<typename Rng>
0035     struct cache1_view : view_facade<cache1_view<Rng>, range_cardinality<Rng>::value>
0036     {
0037     private:
0038         CPP_assert(view_<Rng>);
0039         CPP_assert(input_range<Rng>);
0040         CPP_assert(constructible_from<range_value_t<Rng>, range_reference_t<Rng>>);
0041         friend range_access;
0042         Rng rng_;
0043         bool dirty_ = true;
0044         detail::non_propagating_cache<range_value_t<Rng>> cache_;
0045 
0046         CPP_member
0047         auto update_(range_reference_t<Rng> && val) //
0048             -> CPP_ret(void)(
0049                 requires assignable_from<range_value_t<Rng> &, range_reference_t<Rng>>)
0050         {
0051             if(!cache_)
0052                 cache_.emplace(static_cast<range_reference_t<Rng> &&>(val));
0053             else
0054                 *cache_ = static_cast<range_reference_t<Rng> &&>(val);
0055         }
0056         CPP_member
0057         auto update_(range_reference_t<Rng> && val) //
0058             -> CPP_ret(void)(
0059                 requires (!assignable_from<range_value_t<Rng> &, range_reference_t<Rng>>))
0060         {
0061             cache_.emplace(static_cast<range_reference_t<Rng> &&>(val));
0062         }
0063 
0064         struct cursor;
0065 
0066         struct sentinel
0067         {
0068         private:
0069             friend cursor;
0070             sentinel_t<Rng> last_;
0071 
0072         public:
0073             sentinel() = default;
0074             constexpr explicit sentinel(sentinel_t<Rng> last)
0075               : last_(std::move(last))
0076             {}
0077         };
0078 
0079         struct cursor
0080         {
0081         private:
0082             cache1_view * parent_;
0083             iterator_t<Rng> current_;
0084 
0085         public:
0086             using value_type = range_value_t<Rng>;
0087             using single_pass = std::true_type;
0088             using difference_type = range_difference_t<Rng>;
0089 
0090             cursor() = default;
0091 
0092             constexpr explicit cursor(cache1_view * parent, iterator_t<Rng> current)
0093               : parent_(parent)
0094               , current_(std::move(current))
0095             {}
0096             range_value_t<Rng> && read() const
0097             {
0098                 if(parent_->dirty_)
0099                 {
0100                     parent_->update_(*current_);
0101                     parent_->dirty_ = false;
0102                 }
0103                 return std::move(*parent_->cache_);
0104             }
0105             void next()
0106             {
0107                 ++current_;
0108                 parent_->dirty_ = true;
0109             }
0110             bool equal(cursor const & that) const
0111             {
0112                 return current_ == that.current_;
0113             }
0114             bool equal(sentinel const & that) const
0115             {
0116                 return current_ == that.last_;
0117             }
0118             CPP_member
0119             auto distance_to(cursor const & that) const //
0120                 -> CPP_ret(difference_type)(
0121                     requires sized_sentinel_for<iterator_t<Rng>, iterator_t<Rng>>)
0122             {
0123                 return that.current_ - current_;
0124             }
0125             CPP_member
0126             auto distance_to(sentinel const & that) const //
0127                 -> CPP_ret(difference_type)(
0128                     requires sized_sentinel_for<sentinel_t<Rng>, iterator_t<Rng>>)
0129             {
0130                 return that.last_ - current_;
0131             }
0132         };
0133 
0134         cursor begin_cursor()
0135         {
0136             dirty_ = true;
0137             return cursor{this, ranges::begin(rng_)};
0138         }
0139 
0140         cursor end_cursor_impl(std::true_type)
0141         {
0142             return cursor{this, ranges::end(rng_)};
0143         }
0144         sentinel end_cursor_impl(std::false_type)
0145         {
0146             return sentinel{ranges::end(rng_)};
0147         }
0148         auto end_cursor()
0149         {
0150             return end_cursor_impl(meta::bool_<(bool)common_range<Rng>>{});
0151         }
0152 
0153     public:
0154         cache1_view() = default;
0155         constexpr explicit cache1_view(Rng rng)
0156           : rng_{std::move(rng)}
0157         {}
0158         CPP_auto_member
0159         constexpr auto CPP_fun(size)()(
0160             requires sized_range<Rng>)
0161         {
0162             return ranges::size(rng_);
0163         }
0164     };
0165 
0166 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0167     template<typename Rng>
0168     cache1_view(Rng &&) //
0169         -> cache1_view<views::all_t<Rng>>;
0170 #endif
0171 
0172     namespace views
0173     {
0174         struct cache1_fn
0175         {
0176             /// \brief Caches the most recent element within the view so that
0177             /// dereferencing the view's iterator multiple times doesn't incur any
0178             /// recomputation. This can be useful in adaptor pipelines that include
0179             /// combinations of \c view::filter and \c view::transform, for instance.
0180             /// \note \c views::cache1 is always single-pass.
0181             template(typename Rng)(
0182                 requires viewable_range<Rng> AND input_range<Rng> AND
0183                     constructible_from<range_value_t<Rng>, range_reference_t<Rng>>)
0184             constexpr cache1_view<all_t<Rng>> operator()(Rng && rng) const //
0185             {
0186                 return cache1_view<all_t<Rng>>{all(static_cast<Rng &&>(rng))};
0187             }
0188         };
0189 
0190         /// \relates cache1_fn
0191         /// \ingroup group-views
0192         RANGES_INLINE_VARIABLE(view_closure<cache1_fn>, cache1)
0193     } // namespace views
0194 
0195     /// @}
0196 } // namespace ranges
0197 
0198 #include <range/v3/detail/epilogue.hpp>
0199 #include <range/v3/detail/satisfy_boost_range.hpp>
0200 RANGES_SATISFY_BOOST_RANGE(::ranges::cache1_view)
0201 
0202 #endif