File indexing completed on 2025-01-18 10:09:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
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
0177
0178
0179
0180
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
0191
0192 RANGES_INLINE_VARIABLE(view_closure<cache1_fn>, cache1)
0193 }
0194
0195
0196 }
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