Horizon
view.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 
14 #ifndef RANGES_V3_VIEW_VIEW_HPP
15 #define RANGES_V3_VIEW_VIEW_HPP
16 
17 #include <type_traits>
18 #include <utility>
19 
20 #include <meta/meta.hpp>
21 
22 #include <range/v3/range_fwd.hpp>
23 
30 #include <range/v3/utility/static_const.hpp>
31 
32 #include <range/v3/detail/prologue.hpp>
33 
34 namespace ranges
35 {
38 
40  namespace detail
41  {
42  struct dereference_fn
43  {
44  // clang-format off
45  template<typename I>
46  constexpr auto CPP_auto_fun(operator())(I &&i) (const)
47  (
48  return *(I &&) i
49  )
50  // clang-format on
51  };
52 
53  struct view_closure_base_
54  {};
55  } // namespace detail
57 
58  // clang-format off
61  template(typename Rng)(
62  concept (simple_view_impl_)(Rng),
63  same_as<iterator_t<Rng>, iterator_t<Rng const>> AND
64  same_as<sentinel_t<Rng>, sentinel_t<Rng const>>);
65 
68  template<typename Rng>
69  CPP_concept simple_view_ =
70  view_<Rng> &&
71  range<Rng const> &&
72  CPP_concept_ref(ranges::simple_view_impl_, Rng);
73 
76  template(typename ViewFn, typename Rng)(
77  concept (invocable_view_closure_)(ViewFn, Rng),
78  !derived_from<invoke_result_t<ViewFn, Rng>, detail::view_closure_base_>);
79 
82  template<typename ViewFn, typename Rng>
83  CPP_concept invocable_view_closure =
84  invocable<ViewFn, Rng> &&
85  CPP_concept_ref(ranges::invocable_view_closure_, ViewFn, Rng);
86  // clang-format on
87 
88  template<typename Rng>
89  constexpr bool simple_view() noexcept
90  {
91  return (bool)simple_view_<Rng>;
92  }
93 
95  {
96  template<typename Fun>
97  constexpr views::view_closure<Fun> operator()(Fun fun) const
98  {
99  return views::view_closure<Fun>{static_cast<Fun &&>(fun)};
100  }
101  };
102 
105  RANGES_INLINE_VARIABLE(make_view_closure_fn, make_view_closure)
106 
107  namespace views
108  {
109  struct RANGES_STRUCT_WITH_ADL_BARRIER(view_closure_base)
110  : detail::view_closure_base_
111  {
112  // Piping requires viewable_ranges. Pipeing a value into a closure
113  // should not yield another closure.
114  template(typename Rng, typename ViewFn)(
115  requires viewable_range<Rng> AND
116  invocable_view_closure<ViewFn, Rng>)
117  friend constexpr auto operator|(Rng && rng, view_closure<ViewFn> vw)
118  {
119  return static_cast<ViewFn &&>(vw)(static_cast<Rng &&>(rng));
120  }
121 
122 #ifndef RANGES_WORKAROUND_CLANG_43400
123  // This overload is deleted because when piping a range into an
124  // view, it must be moved in.
125  template<typename Rng, typename ViewFn> // **************************
126  friend constexpr auto // **************************
127  operator|(Rng &&, view_closure<ViewFn> const &) // ******* READ THIS ********
128  // **** IF YOUR COMPILE *****
129  -> CPP_broken_friend_ret(Rng)( // ****** BREAKS HERE *******
130  requires range<Rng> && // **************************
131  (!viewable_range<Rng>)) = delete; // **************************
132  // **************************************************************************
133  // * When piping a range into an adaptor, the range must satisfy the *
134  // * "viewable_range" concept. A range is viewable when either or both *
135  // * of these things are true: *
136  // * - The range is an lvalue (not a temporary object), OR *
137  // * - The range is a view (not a container). *
138  // **************************************************************************
139 #endif
140 
141  template<typename ViewFn, typename Pipeable>
142  friend constexpr auto operator|(view_closure<ViewFn> vw, Pipeable pipe)
143  -> CPP_broken_friend_ret(view_closure<composed<Pipeable, ViewFn>>)(
144  requires (is_pipeable_v<Pipeable>))
145  {
146  return make_view_closure(
147  compose(static_cast<Pipeable &&>(pipe), static_cast<ViewFn &&>(vw)));
148  }
149  };
150 
151 #ifdef RANGES_WORKAROUND_CLANG_43400
152  namespace RANGES_ADL_BARRIER_FOR(view_closure_base)
153  {
154  // This overload is deleted because when piping a range into an
155  // view, it must be moved in.
156  template(typename Rng, typename ViewFn)( // ************************
157  requires range<Rng> AND (!viewable_range<Rng>))// ************************
158  constexpr Rng // ************************
159  operator|(Rng &&, view_closure<ViewFn> const &) // ****** READ THIS *******
160  = delete; // *** IF YOUR COMPILE ****
161  // ***** BREAKS HERE ******
162  // ************************
163  // ************************
164  // ***************************************************************************
165  // * When piping a range into an adaptor, the range must satisfy the *
166  // * "viewable_range" concept. A range is viewable when either or both *
167  // * of these things are true: *
168  // * - The range is an lvalue (not a temporary object), OR *
169  // * - The range is a view (not a container). *
170  // ***************************************************************************
171  } // namespace )
172 #endif // RANGES_WORKAROUND_CLANG_43400
173 
174  template<typename ViewFn>
175  struct RANGES_EMPTY_BASES view_closure
176  : view_closure_base
177  , ViewFn
178  {
179  view_closure() = default;
180 
181  constexpr explicit view_closure(ViewFn fn)
182  : ViewFn(static_cast<ViewFn &&>(fn))
183  {}
184  };
185 
188  struct view_access_
189  {
190  template<typename ViewFn>
191  struct impl
192  {
193  // clang-format off
194  template<typename... Ts, typename V = ViewFn>
195  static constexpr auto CPP_auto_fun(bind)(Ts &&... ts)
196  (
197  return V::bind(static_cast<Ts &&>(ts)...)
198  )
199  // clang-format on
200  };
201  };
202 
203  using view_access RANGES_DEPRECATED(
204  "view_access and views::view<> are deprecated. Please "
205  "replace view<> with view_closure<> and discontinue use of view_access.") =
206  view_access_;
207 
208  template<typename>
209  struct old_view_;
210 
211  struct make_view_fn_
212  {
213  template<typename Fun>
214  constexpr old_view_<Fun> operator()(Fun fun) const
215  {
216  return old_view_<Fun>{static_cast<Fun &&>(fun)};
217  }
218  };
219  using make_view_fn RANGES_DEPRECATED(
220  "make_view_fn is deprecated. Please use "
221  "make_view_closure instead.") = make_view_fn_;
222 
223  namespace
224  {
225  RANGES_DEPRECATED(
226  "make_view and views::view<> has been deprecated. Please switch to "
227  "make_view_closure and views::view_closure.")
228  RANGES_INLINE_VAR constexpr auto & make_view =
229  static_const<make_view_fn_>::value;
230  } // namespace
231 
232  template<typename ViewFn>
233  struct old_view_ : pipeable_base
234  {
235  private:
236  ViewFn vw_;
237  friend pipeable_access;
238 
239  // Piping requires range arguments or lvalue containers.
240  template(typename Rng, typename Vw)(
241  requires viewable_range<Rng> AND invocable<ViewFn &, Rng>)
242  static constexpr auto pipe(Rng && rng, Vw && v)
243  {
244  return v.vw_(static_cast<Rng &&>(rng));
245  }
246 
247  public:
248  old_view_() = default;
249 
250  constexpr explicit old_view_(ViewFn a) noexcept(
251  std::is_nothrow_move_constructible<ViewFn>::value)
252  : vw_(std::move(a))
253  {}
254 
255  // Calling directly requires a viewable_range.
256  template(typename Rng, typename... Rest)(
257  requires viewable_range<Rng> AND invocable<ViewFn const &, Rng, Rest...>)
258  constexpr invoke_result_t<ViewFn const &, Rng, Rest...> //
259  operator()(Rng && rng, Rest &&... rest) const
260  {
261  return vw_(static_cast<Rng &&>(rng), static_cast<Rest &&>(rest)...);
262  }
263 
264  // Currying overload.
265  // clang-format off
266  template<typename... Ts, typename V = ViewFn>
267  constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(const)
268  (
269  return make_view_fn_{}(
270  view_access_::impl<V>::bind(vw_, static_cast<Ts &&>(ts)...))
271  )
272  // clang-format on
273  };
274 
275  template<typename ViewFn>
276  using view RANGES_DEPRECATED(
277  "The views::view<> template is deprecated. Please switch to view_closure") =
278  old_view_<ViewFn>;
280  } // namespace views
281 
282  template<typename ViewFn>
283  RANGES_INLINE_VAR constexpr bool is_pipeable_v<views::view_closure<ViewFn>> = true;
285 } // namespace ranges
286 
287 #include <range/v3/detail/epilogue.hpp>
288 
289 #endif
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
CPP_concept simple_view_
\concept simple_view_
Definition: view.hpp:69
template(typename ViewFn, typename Rng)(concept(invocable_view_closure_)(ViewFn
\concept invocable_view_closure_
CPP_concept invocable_view_closure
\concept invocable_view_closure
Definition: view.hpp:83
Tiny meta-programming library.
Definition: view.hpp:95
Definition: view.hpp:178