Horizon
cache1.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2014-present
5 //
6 // Use, modification and distribution is subject to the
7 // Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Project home: https://github.com/ericniebler/range-v3
12 //
13 #ifndef RANGES_V3_VIEW_CACHE1_HPP
14 #define RANGES_V3_VIEW_CACHE1_HPP
15 
16 #include <range/v3/range_fwd.hpp>
17 
26 #include <range/v3/view/all.hpp>
27 
28 #include <range/v3/detail/prologue.hpp>
29 
30 namespace ranges
31 {
34  template<typename Rng>
35  struct cache1_view : view_facade<cache1_view<Rng>, range_cardinality<Rng>::value>
36  {
37  private:
38  CPP_assert(view_<Rng>);
39  CPP_assert(input_range<Rng>);
40  CPP_assert(constructible_from<range_value_t<Rng>, range_reference_t<Rng>>);
41  friend range_access;
42  Rng rng_;
43  bool dirty_ = true;
44  detail::non_propagating_cache<range_value_t<Rng>> cache_;
45 
46  CPP_member
47  auto update_(range_reference_t<Rng> && val) //
48  -> CPP_ret(void)(
49  requires assignable_from<range_value_t<Rng> &, range_reference_t<Rng>>)
50  {
51  if(!cache_)
52  cache_.emplace(static_cast<range_reference_t<Rng> &&>(val));
53  else
54  *cache_ = static_cast<range_reference_t<Rng> &&>(val);
55  }
56  CPP_member
57  auto update_(range_reference_t<Rng> && val) //
58  -> CPP_ret(void)(
59  requires (!assignable_from<range_value_t<Rng> &, range_reference_t<Rng>>))
60  {
61  cache_.emplace(static_cast<range_reference_t<Rng> &&>(val));
62  }
63 
64  struct cursor;
65 
66  struct sentinel
67  {
68  private:
69  friend cursor;
70  sentinel_t<Rng> last_;
71 
72  public:
73  sentinel() = default;
74  constexpr explicit sentinel(sentinel_t<Rng> last)
75  : last_(std::move(last))
76  {}
77  };
78 
79  struct cursor
80  {
81  private:
82  cache1_view * parent_;
83  iterator_t<Rng> current_;
84 
85  public:
86  using value_type = range_value_t<Rng>;
87  using single_pass = std::true_type;
88  using difference_type = range_difference_t<Rng>;
89 
90  cursor() = default;
91 
92  constexpr explicit cursor(cache1_view * parent, iterator_t<Rng> current)
93  : parent_(parent)
94  , current_(std::move(current))
95  {}
96  range_value_t<Rng> && read() const
97  {
98  if(parent_->dirty_)
99  {
100  parent_->update_(*current_);
101  parent_->dirty_ = false;
102  }
103  return std::move(*parent_->cache_);
104  }
105  void next()
106  {
107  ++current_;
108  parent_->dirty_ = true;
109  }
110  bool equal(cursor const & that) const
111  {
112  return current_ == that.current_;
113  }
114  bool equal(sentinel const & that) const
115  {
116  return current_ == that.last_;
117  }
118  CPP_member
119  auto distance_to(cursor const & that) const //
120  -> CPP_ret(difference_type)(
121  requires sized_sentinel_for<iterator_t<Rng>, iterator_t<Rng>>)
122  {
123  return that.current_ - current_;
124  }
125  CPP_member
126  auto distance_to(sentinel const & that) const //
127  -> CPP_ret(difference_type)(
128  requires sized_sentinel_for<sentinel_t<Rng>, iterator_t<Rng>>)
129  {
130  return that.last_ - current_;
131  }
132  };
133 
134  cursor begin_cursor()
135  {
136  dirty_ = true;
137  return cursor{this, ranges::begin(rng_)};
138  }
139 
140  cursor end_cursor_impl(std::true_type)
141  {
142  return cursor{this, ranges::end(rng_)};
143  }
144  sentinel end_cursor_impl(std::false_type)
145  {
146  return sentinel{ranges::end(rng_)};
147  }
148  auto end_cursor()
149  {
150  return end_cursor_impl(meta::bool_<(bool)common_range<Rng>>{});
151  }
152 
153  public:
154  cache1_view() = default;
155  constexpr explicit cache1_view(Rng rng)
156  : rng_{std::move(rng)}
157  {}
158  CPP_auto_member
159  constexpr auto CPP_fun(size)()(
160  requires sized_range<Rng>)
161  {
162  return ranges::size(rng_);
163  }
164  };
165 
166 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
167  template<typename Rng>
168  cache1_view(Rng &&) //
170 #endif
171 
172  namespace views
173  {
174  struct cache1_fn
175  {
181  template(typename Rng)(
182  requires viewable_range<Rng> AND input_range<Rng> AND
183  constructible_from<range_value_t<Rng>, range_reference_t<Rng>>)
184  constexpr cache1_view<all_t<Rng>> operator()(Rng && rng) const //
185  {
186  return cache1_view<all_t<Rng>>{all(static_cast<Rng &&>(rng))};
187  }
188  };
189 
192  RANGES_INLINE_VARIABLE(view_closure<cache1_fn>, cache1)
193  } // namespace views
194 
196 } // namespace ranges
197 
198 #include <range/v3/detail/epilogue.hpp>
199 #include <range/v3/detail/satisfy_boost_range.hpp>
200 RANGES_SATISFY_BOOST_RANGE(::ranges::cache1_view)
201 
202 #endif
decltype(begin(declval(Rng &))) iterator_t
Definition: access.hpp:698
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
Definition: cache1.hpp:36
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition: facade.hpp:66
Definition: cache1.hpp:175