Horizon
Loading...
Searching...
No Matches
interface.hpp
Go to the documentation of this file.
1
2// 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_INTERFACE_HPP
14#define RANGES_V3_VIEW_INTERFACE_HPP
15
16#include <iosfwd>
17
18#include <meta/meta.hpp>
19
20#include <concepts/concepts.hpp>
21
23
30
31#include <range/v3/detail/prologue.hpp>
32
33#if defined(RANGES_WORKAROUND_GCC_91525)
34#define CPP_template_gcc_workaround CPP_template_sfinae
35#else
36#define CPP_template_gcc_workaround template
37#endif
38
39namespace ranges
40{
42 namespace detail
43 {
44 template<typename From, typename To = From>
45 struct slice_bounds
46 {
47 From from;
48 To to;
49 template(typename F, typename T)(
50 requires convertible_to<F, From> AND convertible_to<T, To>)
51 constexpr slice_bounds(F f, T t)
52 : from(static_cast<From>(f))
53 , to(static_cast<To>(t))
54 {}
55 };
56
57 template<typename Int>
58 struct from_end_
59 {
60 Int dist_;
61
62 constexpr explicit from_end_(Int dist)
63 : dist_(dist)
64 {}
65
66 template(typename Other)(
67 requires integer_like_<Other> AND explicitly_convertible_to<Other, Int>)
68 constexpr operator from_end_<Other>() const
69 {
70 return from_end_<Other>{static_cast<Other>(dist_)};
71 }
72 };
73
74 template<typename Rng>
75 using from_end_of_t = from_end_<range_difference_t<Rng>>;
76
77 // clang-format off
80 template<typename Rng>
81 CPP_requires(_can_empty_,
82 requires(Rng & rng) //
83 (
84 ranges::empty(rng)
85 ));
88 template<typename Rng>
89 CPP_concept can_empty_ = //
90 CPP_requires_ref(detail::_can_empty_, Rng);
91 // clang-format on
92
93 template<cardinality C>
94 RANGES_INLINE_VAR constexpr bool has_fixed_size_ = (C >= 0 || C == infinite);
95
96 template<bool>
97 struct dependent_
98 {
99 template<typename T>
100 using invoke = T;
101 };
102
103 template<typename Stream, typename Rng>
104 Stream & print_rng_(Stream & sout, Rng & rng)
105 {
106 sout << '[';
107 auto it = ranges::begin(rng);
108 auto const e = ranges::end(rng);
109 if(it != e)
110 {
111 for(;;)
112 {
113 sout << *it;
114 if(++it == e)
115 break;
116 sout << ',';
117 }
118 }
119 sout << ']';
120 return sout;
121 }
122 } // namespace detail
124
127 template<typename Derived, cardinality Cardinality /* = finite*/>
128 struct view_interface : basic_view<Cardinality>
129 {
130 protected:
131 template<bool B>
132 using D = meta::invoke<detail::dependent_<B>, Derived>;
133
134 constexpr Derived & derived() noexcept
135 {
136 CPP_assert(derived_from<Derived, view_interface>);
137 return static_cast<Derived &>(*this);
138 }
140 constexpr Derived const & derived() const noexcept
141 {
142 CPP_assert(derived_from<Derived, view_interface>);
143 return static_cast<Derived const &>(*this);
144 }
145
146 public:
147 view_interface() = default;
148 view_interface(view_interface &&) = default;
149 view_interface(view_interface const &) = default;
150 view_interface & operator=(view_interface &&) = default;
151 view_interface & operator=(view_interface const &) = default;
153 CPP_member
154 constexpr auto empty() const noexcept //
155 -> CPP_ret(bool)(
156 requires (detail::has_fixed_size_<Cardinality>))
157 {
158 return Cardinality == 0;
159 }
161 template(bool True = true)(
162 requires True AND (Cardinality < 0) AND (Cardinality != infinite) AND
163 (!forward_range<D<True>>) AND sized_range<D<True>>)
164 constexpr bool empty() //
165 noexcept(noexcept(bool(ranges::size(std::declval<D<True> &>()) == 0)))
166 {
167 return ranges::size(derived()) == 0;
168 }
170 template(bool True = true)(
171 requires True AND (Cardinality < 0) AND (Cardinality != infinite) AND
172 (!forward_range<D<True> const>) AND sized_range<D<True> const>)
173 constexpr bool empty() const //
174 noexcept(noexcept(bool(ranges::size(std::declval<D<True> const &>()) == 0)))
175 {
176 return ranges::size(derived()) == 0;
177 }
179 template(bool True = true)(
180 requires True AND (!detail::has_fixed_size_<Cardinality>) AND
181 forward_range<D<True>>)
182 constexpr bool empty() noexcept(
183 noexcept(bool(ranges::begin(std::declval<D<True> &>()) ==
184 ranges::end(std::declval<D<True> &>()))))
185 {
186 return bool(ranges::begin(derived()) == ranges::end(derived()));
187 }
189 template(bool True = true)(
190 requires True AND (!detail::has_fixed_size_<Cardinality>) AND
191 forward_range<D<True> const>)
192 constexpr bool empty() const
193 noexcept(noexcept(bool(ranges::begin(std::declval<D<True> const &>()) ==
194 ranges::end(std::declval<D<True> const &>()))))
195 {
196 return bool(ranges::begin(derived()) == ranges::end(derived()));
197 }
198 CPP_template_gcc_workaround(bool True = true)(
199 requires True && detail::can_empty_<D<True>>) // clang-format off
200 constexpr explicit operator bool()
201 noexcept(noexcept(ranges::empty(std::declval<D<True> &>())))
202 {
203 return !ranges::empty(derived());
204 }
205 // clang-format on
207 CPP_template_gcc_workaround(bool True = true)(
208 requires True && detail::can_empty_<D<True> const>) // clang-format off
209 constexpr explicit operator bool() const
210 noexcept(noexcept(ranges::empty(std::declval<D<True> const &>())))
211 {
212 return !ranges::empty(derived());
213 }
214 // clang-format on
217 template(bool True = true, int = 42)(
218 requires True AND (Cardinality >= 0)) //
219 static constexpr std::size_t size() noexcept
220 {
221 return static_cast<std::size_t>(Cardinality);
222 }
226 template(bool True = true)(
227 requires True AND (Cardinality < 0) AND
228 sized_sentinel_for<sentinel_t<D<True>>, iterator_t<D<True>>> AND
229 forward_range<D<True>>)
230 constexpr detail::iter_size_t<iterator_t<D<True>>> size()
231 {
232 using size_type = detail::iter_size_t<iterator_t<D<True>>>;
233 return static_cast<size_type>(derived().end() - derived().begin());
234 }
236 template(bool True = true)(
237 requires True AND (Cardinality < 0) AND
238 sized_sentinel_for<sentinel_t<D<True> const>,
239 iterator_t<D<True> const>> AND
240 forward_range<D<True> const>)
241 constexpr detail::iter_size_t<iterator_t<D<True>>> size() const //
242 {
243 using size_type = detail::iter_size_t<iterator_t<D<True>>>;
244 return static_cast<size_type>(derived().end() - derived().begin());
245 }
247 template(bool True = true)(
248 requires True AND forward_range<D<True>>)
249 constexpr range_reference_t<D<True>> front()
250 {
251 return *derived().begin();
252 }
254 template(bool True = true)(
255 requires True AND forward_range<D<True> const>)
256 constexpr range_reference_t<D<True> const> front() const
257 {
258 return *derived().begin();
259 }
261 template(bool True = true)(
262 requires True AND common_range<D<True>> AND bidirectional_range<D<True>>)
263 constexpr range_reference_t<D<True>> back()
264 {
265 return *prev(derived().end());
266 }
268 template(bool True = true)(
269 requires True AND common_range<D<True> const> AND
270 bidirectional_range<D<True> const>)
271 constexpr range_reference_t<D<True> const> back() const
272 {
273 return *prev(derived().end());
274 }
276 template(bool True = true)(
277 requires True AND random_access_range<D<True>>)
278 constexpr range_reference_t<D<True>> operator[](range_difference_t<D<True>> n)
279 {
280 return derived().begin()[n];
281 }
283 template(bool True = true)(
284 requires True AND random_access_range<D<True> const>)
285 constexpr range_reference_t<D<True> const> //
286 operator[](range_difference_t<D<True>> n) const
287 {
288 return derived().begin()[n];
289 }
292 template(bool True = true)(
293 requires True AND contiguous_iterator<iterator_t<D<True>>>)
294 constexpr std::add_pointer_t<range_reference_t<D<True>>> data() //
295 {
296 return std::addressof(*ranges::begin(derived()));
297 }
299 template(bool True = true)(
300 requires True AND contiguous_iterator<iterator_t<D<True> const>>)
301 constexpr std::add_pointer_t<range_reference_t<D<True> const>> data() const //
302 {
303 return std::addressof(*ranges::begin(derived()));
304 }
307 template(bool True = true)(
308 requires True AND random_access_range<D<True>> AND sized_range<D<True>>)
309 constexpr range_reference_t<D<True>> at(range_difference_t<D<True>> n)
310 {
311 using size_type = range_size_t<Derived>;
312 if(n < 0 || size_type(n) >= ranges::size(derived()))
313 {
314 throw std::out_of_range("view_interface::at");
315 }
316 return derived().begin()[n];
317 }
319 template(bool True = true)(
320 requires True AND random_access_range<D<True> const> AND
321 sized_range<D<True> const>)
322 constexpr range_reference_t<D<True> const> at(range_difference_t<D<True>> n) const
323 {
324 using size_type = range_size_t<Derived const>;
325 if(n < 0 || size_type(n) >= ranges::size(derived()))
326 {
327 throw std::out_of_range("view_interface::at");
328 }
329 return derived().begin()[n];
330 }
332 // rng[{4,6}]
333 template(bool True = true, typename Slice = views::slice_fn)(
334 requires True AND input_range<D<True> &>)
335 constexpr auto
336 operator[](detail::slice_bounds<range_difference_t<D<True>>> offs) &
337 {
338 return Slice{}(derived(), offs.from, offs.to);
339 }
341 template(bool True = true, typename Slice = views::slice_fn)(
342 requires True AND input_range<D<True> const &>)
343 constexpr auto
344 operator[](detail::slice_bounds<range_difference_t<D<True>>> offs) const &
345 {
346 return Slice{}(derived(), offs.from, offs.to);
347 }
349 template(bool True = true, typename Slice = views::slice_fn)(
350 requires True AND input_range<D<True>>)
351 constexpr auto
352 operator[](detail::slice_bounds<range_difference_t<D<True>>> offs) &&
353 {
354 return Slice{}(detail::move(derived()), offs.from, offs.to);
355 }
356 // rng[{4,end-2}]
358 template(bool True = true, typename Slice = views::slice_fn)(
359 requires True AND input_range<D<True> &> AND sized_range<D<True> &>)
360 constexpr auto //
361 operator[](detail::slice_bounds<range_difference_t<D<True>>,
362 detail::from_end_of_t<D<True>>> offs) &
363 {
364 return Slice{}(derived(), offs.from, offs.to);
365 }
367 template(bool True = true, typename Slice = views::slice_fn)(
368 requires True AND input_range<D<True> const &> AND
369 sized_range<D<True> const &>)
370 constexpr auto //
371 operator[](detail::slice_bounds<range_difference_t<D<True>>,
372 detail::from_end_of_t<D<True>>> offs) const &
373 {
374 return Slice{}(derived(), offs.from, offs.to);
375 }
377 template(bool True = true, typename Slice = views::slice_fn)(
378 requires True AND input_range<D<True>> AND sized_range<D<True>>)
379 constexpr auto //
380 operator[](detail::slice_bounds<range_difference_t<D<True>>,
381 detail::from_end_of_t<D<True>>> offs) &&
382 {
383 return Slice{}(detail::move(derived()), offs.from, offs.to);
384 }
385 // rng[{end-4,end-2}]
387 template(bool True = true, typename Slice = views::slice_fn)(
388 requires True AND (forward_range<D<True> &> ||
389 (input_range<D<True> &> && sized_range<D<True> &>))) //
390 constexpr auto //
391 operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>,
392 detail::from_end_of_t<D<True>>> offs) &
393 {
394 return Slice{}(derived(), offs.from, offs.to);
395 }
397 template(bool True = true, typename Slice = views::slice_fn)(
398 requires True AND
399 (forward_range<D<True> const &> ||
400 (input_range<D<True> const &> && sized_range<D<True> const &>))) //
401 constexpr auto //
402 operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>,
403 detail::from_end_of_t<D<True>>> offs) const &
404 {
405 return Slice{}(derived(), offs.from, offs.to);
406 }
408 template(bool True = true, typename Slice = views::slice_fn)(
409 requires True AND
410 (forward_range<D<True>> ||
411 (input_range<D<True>> && sized_range<D<True>>))) //
412 constexpr auto //
413 operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>,
414 detail::from_end_of_t<D<True>>> offs) &&
415 {
416 return Slice{}(detail::move(derived()), offs.from, offs.to);
417 }
418 // rng[{4,end}]
420 template(bool True = true, typename Slice = views::slice_fn)(
421 requires True AND input_range<D<True> &>)
422 constexpr auto //
423 operator[](detail::slice_bounds<range_difference_t<D<True>>, end_fn> offs) &
424 {
425 return Slice{}(derived(), offs.from, offs.to);
426 }
428 template(bool True = true, typename Slice = views::slice_fn)(
429 requires True AND input_range<D<True> const &>)
430 constexpr auto //
431 operator[](detail::slice_bounds<range_difference_t<D<True>>, end_fn> offs) const &
432 {
433 return Slice{}(derived(), offs.from, offs.to);
434 }
436 template(bool True = true, typename Slice = views::slice_fn)(
437 requires True AND input_range<D<True>>)
438 constexpr auto //
439 operator[](detail::slice_bounds<range_difference_t<D<True>>, end_fn> offs) &&
440 {
441 return Slice{}(detail::move(derived()), offs.from, offs.to);
442 }
443 // rng[{end-4,end}]
445 template(bool True = true, typename Slice = views::slice_fn)(
446 requires True AND
447 (forward_range<D<True> &> ||
448 (input_range<D<True> &> && sized_range<D<True> &>))) //
449 constexpr auto //
450 operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>, end_fn> offs) &
451 {
452 return Slice{}(derived(), offs.from, offs.to);
453 }
455 template(bool True = true, typename Slice = views::slice_fn)(
456 requires True AND
457 (forward_range<D<True> const &> ||
458 (input_range<D<True> const &> && sized_range<D<True> const &>))) //
459 constexpr auto //
460 operator[](
461 detail::slice_bounds<detail::from_end_of_t<D<True>>, end_fn> offs) const &
462 {
463 return Slice{}(derived(), offs.from, offs.to);
464 }
466 template(bool True = true, typename Slice = views::slice_fn)(
467 requires True AND
468 (forward_range<D<True>> ||
469 (input_range<D<True>> && sized_range<D<True>>))) //
470 constexpr auto //
471 operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>, end_fn> offs) &&
472 {
473 return Slice{}(detail::move(derived()), offs.from, offs.to);
474 }
475 private:
476#ifndef RANGES_V3_DISABLE_IO
478 template<bool True = true>
479 friend auto operator<<(std::ostream & sout, Derived const & rng)
480 -> CPP_broken_friend_ret(std::ostream &)(
481 requires True && input_range<D<True> const>)
482 {
483 return detail::print_rng_(sout, rng);
484 }
486 template<bool True = true>
487 friend auto operator<<(std::ostream & sout, Derived & rng)
488 -> CPP_broken_friend_ret(std::ostream &)(
489 requires True && (!range<D<True> const>) && input_range<D<True>>)
490 {
491 return detail::print_rng_(sout, rng);
492 }
494 template<bool True = true>
495 friend auto operator<<(std::ostream & sout, Derived && rng)
496 -> CPP_broken_friend_ret(std::ostream &)(
497 requires True && (!range<D<True> const>) && input_range<D<True>>)
498 {
499 return detail::print_rng_(sout, rng);
500 }
501#endif
502 };
503 namespace cpp20
504 {
505 template(typename Derived)(
506 requires std::is_class<Derived>::value AND
507 same_as<Derived, meta::_t<std::remove_cv<Derived>>>)
509 }
511} // namespace ranges
512
513#include <range/v3/detail/epilogue.hpp>
514
515#endif
The forward_range concept.
The sized_range concept.
decltype(begin(declval(Rng &))) iterator_t
Definition access.hpp:698
typename T::type _t
Type alias for T::type.
Definition meta.hpp:141
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition meta.hpp:541
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition meta.hpp:1696
_t< detail::back_< L > > back
Return the last element in meta::list L.
Definition meta.hpp:2103
at_c< L, N::type::value > at
Return the N th element in the meta::list L.
Definition meta.hpp:1969
_t< detail::front_< L > > front
Return the first element in meta::list L.
Definition meta.hpp:2070
Tiny meta-programming library.
Definition range_fwd.hpp:549
Definition interface.hpp:129
constexpr Derived const & derived() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition interface.hpp:140
CPP_member constexpr auto empty() const noexcept -> CPP_ret(bool)()
Test whether a range can be empty:
Definition interface.hpp:154