13 #ifndef RANGES_V3_VIEW_ADAPTOR_HPP
14 #define RANGES_V3_VIEW_ADAPTOR_HPP
31 #include <range/v3/detail/prologue.hpp>
38 template<
typename Derived>
39 using begin_adaptor_t = detail::decay_t<decltype(
40 range_access::begin_adaptor(std::declval<Derived &>()))>;
42 template<
typename Derived>
43 using end_adaptor_t = detail::decay_t<decltype(
44 range_access::end_adaptor(std::declval<Derived &>()))>;
46 template<
typename Derived>
47 using adapted_iterator_t = detail::decay_t<decltype(
48 std::declval<begin_adaptor_t<Derived>>().begin(std::declval<Derived &>()))>;
50 template<
typename Derived>
51 using adapted_sentinel_t = detail::decay_t<decltype(
52 std::declval<end_adaptor_t<Derived>>().end(std::declval<Derived &>()))>;
54 struct adaptor_base_current_mem_fn
57 template<
typename BaseIter,
typename Adapt>
58 constexpr
int which_adaptor_value_(priority_tag<0>)
62 template<
typename BaseIter,
typename Adapt>
63 constexpr always_<int, decltype(Adapt::read(std::declval<BaseIter const &>(),
64 adaptor_base_current_mem_fn{}))>
65 which_adaptor_value_(priority_tag<1>)
69 template<
typename BaseIter,
typename Adapt>
70 constexpr always_<int, typename Adapt::value_type>
71 which_adaptor_value_(priority_tag<2>)
76 template<
typename BaseIter,
typename Adapt,
77 int = detail::which_adaptor_value_<BaseIter, Adapt>(priority_tag<2>{})>
78 struct adaptor_value_type_
80 compressed_pair<BaseIter, Adapt> data_;
82 template<
typename BaseIter,
typename Adapt>
83 struct adaptor_value_type_<BaseIter, Adapt, 1>
85 using value_type = iter_value_t<BaseIter>;
86 compressed_pair<BaseIter, Adapt> data_;
88 template<
typename BaseIter,
typename Adapt>
89 struct adaptor_value_type_<BaseIter, Adapt, 2>
91 #ifdef RANGES_WORKAROUND_MSVC_688606
92 using value_type =
typename indirectly_readable_traits<Adapt>::value_type;
94 using value_type =
typename Adapt::value_type;
96 compressed_pair<BaseIter, Adapt> data_;
103 template<
typename BaseIt,
typename Adapt>
104 struct adaptor_cursor;
106 template<
typename BaseSent,
typename Adapt>
107 struct base_adaptor_sentinel;
117 adaptor_base(detail::ignore_t, detail::ignore_t = {}, detail::ignore_t = {})
120 template<
typename Rng>
121 static constexpr
auto CPP_auto_fun(begin)(Rng &rng)
123 return ranges::begin(rng.base())
125 template<typename Rng>
126 static constexpr
auto CPP_auto_fun(end)(Rng &rng)
128 return ranges::end(rng.base())
131 template(
typename I)(
132 requires equality_comparable<I>)
133 static bool equal(I
const & it0, I
const & it1)
137 template(
typename I)(
138 requires input_or_output_iterator<I>)
139 static iter_reference_t<I> read(I
const & it,
140 detail::adaptor_base_current_mem_fn = {})
141 noexcept(noexcept(iter_reference_t<I>(*it)))
145 template(
typename I)(
146 requires input_or_output_iterator<I>)
147 static void next(I & it)
151 template(
typename I)(
152 requires bidirectional_iterator<I>)
153 static void prev(I & it)
157 template(
typename I)(
158 requires random_access_iterator<I>)
159 static void advance(I & it, iter_difference_t<I> n)
163 template(
typename I)(
164 requires sized_sentinel_for<I, I>)
165 static iter_difference_t<I> distance_to(I
const & it0, I
const & it1)
169 template(
typename I,
typename S)(
170 requires sentinel_for<S, I>)
171 static constexpr
bool empty(I
const & it, S
const & last)
179 template<
typename BaseSent,
typename Adapt>
183 template<
typename,
typename>
190 : data_{std::move(sent), std::move(adapt)}
195 BaseSent base()
const
197 return data_.first();
204 return data_.second();
206 Adapt
const & get()
const
208 return data_.second();
215 template<
typename BaseSent,
typename Adapt>
218 template<
typename BaseSent,
typename Adapt>
220 base_adaptor_sentinel_2_(
int);
222 template<
typename BaseSent,
typename Adapt>
223 struct base_adaptor_sentinel_
224 : decltype(base_adaptor_sentinel_2_<BaseSent, Adapt>(42))
227 template<
typename BaseSent,
typename Adapt>
232 template<
typename BaseSent,
typename Adapt>
235 using detail::adaptor_sentinel_<BaseSent, Adapt>::adaptor_sentinel_;
240 template<
typename BaseIter,
typename Adapt>
245 template<
typename,
typename>
247 using base_t = detail::adaptor_value_type_<BaseIter, Adapt>;
249 (bool)single_pass_iterator_<BaseIter>>;
251 struct basic_adaptor_mixin :
basic_mixin<adaptor_cursor>
253 basic_adaptor_mixin() =
default;
260 constexpr
explicit basic_adaptor_mixin(
adaptor_cursor const & cur)
266 BaseIter base()
const
268 return basic_adaptor_mixin::basic_mixin::get().data_.first();
275 return basic_adaptor_mixin::basic_mixin::get().data_.second();
277 const Adapt & get()
const
279 return basic_adaptor_mixin::basic_mixin::get().data_.second();
283 template<
typename Adapt_>
286 template<
typename Adapt_>
288 basic_adaptor_mixin_2_(
int);
292 template<typename A = Adapt, typename R = decltype(std::declval<A const &>().read(
293 std::declval<BaseIter const &>()))>
294 R read()
const noexcept(
295 noexcept(std::declval<A const &>().read(std::declval<BaseIter const &>())))
297 using V = range_access::cursor_value_t<adaptor_cursor>;
298 static_assert(common_reference_with<R &&, V &>,
299 "In your adaptor, you've specified a value type that does not "
300 "share a common reference type with the return type of read.");
301 return this->data_.second().read(this->data_.first());
303 template<typename A = Adapt, typename = decltype(std::declval<A &>().next(
304 std::declval<BaseIter &>()))>
307 this->data_.second().next(this->data_.first());
309 template<
typename A = Adapt,
310 typename = decltype(std::declval<A const &>().equal(
311 std::declval<BaseIter const &>(), std::declval<BaseIter const &>(),
312 std::declval<A const &>()))>
315 return this->data_.second().equal(
316 this->data_.first(), that.data_.first(), that.data_.second());
318 template<
typename A = Adapt,
319 typename = decltype(std::declval<A const &>().equal(
320 std::declval<BaseIter const &>(), std::declval<BaseIter const &>()))>
323 return this->data_.second().equal(this->data_.first(), that.data_.first());
325 template<
typename C = adaptor_cursor>
327 -> decltype(std::declval<C const &>().equal_(that, 42))
329 return this->equal_(that, 42);
331 template<
typename S,
typename A,
332 typename = decltype(std::declval<A const &>().
empty(
333 std::declval<BaseIter const &>(), std::declval<Adapt const &>(),
334 std::declval<S const &>()))>
337 return that.data_.second().empty(
338 this->data_.first(), this->data_.second(), that.data_.first());
340 template<
typename S,
typename A,
341 typename = decltype(std::declval<A const &>().
empty(
342 std::declval<BaseIter const &>(), std::declval<S const &>()))>
345 return that.data_.second().empty(this->data_.first(), that.data_.first());
347 template<
typename S,
typename A>
349 -> decltype(std::declval<adaptor_cursor const &>().equal_(that, 42))
351 return this->equal_(that, 42);
353 template<typename A = Adapt, typename = decltype(std::declval<A &>().prev(
354 std::declval<BaseIter &>()))>
357 this->data_.second().prev(this->data_.first());
359 template<typename A = Adapt, typename = decltype(std::declval<A &>().advance(
360 std::declval<BaseIter &>(), 0))>
361 void advance(iter_difference_t<BaseIter> n)
363 this->data_.second().advance(this->data_.first(), n);
365 template<
typename A = Adapt,
366 typename R = decltype(std::declval<A const &>().distance_to(
367 std::declval<BaseIter const &>(), std::declval<BaseIter const &>(),
368 std::declval<A const &>()))>
371 return this->data_.second().distance_to(
372 this->data_.first(), that.data_.first(), that.data_.second());
374 template<
typename A = Adapt,
375 typename R = decltype(std::declval<A const &>().distance_to(
376 std::declval<BaseIter const &>(), std::declval<BaseIter const &>()))>
379 return this->data_.second().distance_to(this->data_.first(),
382 template<
typename C = adaptor_cursor>
384 -> decltype(std::declval<C const &>().distance_to_(that, 42))
386 return this->distance_to_(that, 42);
389 template<
typename A = Adapt,
390 typename X = decltype(std::declval<A const &>().iter_move(
391 std::declval<BaseIter const &>()))>
392 X iter_move_(
int)
const noexcept(noexcept(
393 std::declval<A const &>().iter_move(std::declval<BaseIter const &>())))
395 using V = range_access::cursor_value_t<adaptor_cursor>;
396 using R = decltype(this->data_.second().read(this->data_.first()));
398 common_reference_with<X &&, V const &>,
399 "In your adaptor, the result of your iter_move member function does "
400 "not share a common reference with your value type.");
402 common_reference_with<R &&, X &&>,
403 "In your adaptor, the result of your iter_move member function does "
404 "not share a common reference with the result of your read member "
406 return this->data_.second().iter_move(this->data_.first());
410 template<
typename A = Adapt,
411 typename R = decltype(std::declval<A const &>().read(
412 std::declval<BaseIter const &>(),
413 detail::adaptor_base_current_mem_fn{})),
414 typename X = iter_rvalue_reference_t<BaseIter>>
415 X iter_move_(
long)
const
416 noexcept(noexcept(X(ranges::iter_move(std::declval<BaseIter const &>()))))
418 return ranges::iter_move(this->data_.first());
422 template<
typename A = Adapt,
423 typename R = decltype(
424 std::declval<A const &>().read(std::declval<BaseIter const &>())),
426 X iter_move_(detail::ignore_t)
const noexcept(noexcept(X(
static_cast<X &&
>(
427 std::declval<A const &>().read(std::declval<BaseIter const &>())))))
429 using V = range_access::cursor_value_t<adaptor_cursor>;
431 common_reference_with<X &&, V const &>,
432 "In your adaptor, you've specified a value type that does not share a "
434 "reference type with the result of moving the result of the read member "
435 "function. Consider defining an iter_move function in your adaptor.");
436 return static_cast<X &&
>(this->data_.second().read(this->data_.first()));
440 noexcept(noexcept(std::declval<const adaptor_cursor &>().iter_move_(42)))
441 -> decltype(std::declval<const adaptor_cursor &>().iter_move_(42))
443 return iter_move_(42);
449 : base_t{{std::move(iter), std::move(adapt)}}
451 template(
typename OtherIter,
typename OtherAdapt)(
454 convertible_to<OtherIter, BaseIter> AND
455 convertible_to<OtherAdapt, Adapt>)
457 : base_t{{std::move(that.data_.first()), std::move(that.data_.second())}}
466 using adaptor_sentinel_t = meta::if_c<
467 same_as<detail::adapted_iterator_t<D>, detail::adapted_sentinel_t<D>> &&
468 same_as<detail::begin_adaptor_t<D>, detail::end_adaptor_t<D>>,
472 template<
typename Derived,
typename BaseRng,
473 cardinality Cardinality >
480 CPP_assert(viewable_range<BaseRng>);
481 using base_range_t = views::all_t<BaseRng>;
498 range_access::begin_adaptor(d)}))
500 auto adapt = range_access::begin_adaptor(d);
501 auto pos = adapt.begin(d);
502 return {std::move(pos), std::move(adapt)};
504 template(
typename D = Derived)(
505 requires same_as<D, Derived>)
506 constexpr
auto begin_cursor() noexcept(
507 noexcept(view_adaptor::begin_cursor_(std::declval<D &>())))
508 -> decltype(view_adaptor::begin_cursor_(std::declval<D &>()))
510 return view_adaptor::begin_cursor_(derived());
512 template(
typename D = Derived)(
513 requires same_as<D, Derived> AND range<base_range_t const>)
514 constexpr
auto begin_cursor()
const
515 noexcept(noexcept(view_adaptor::begin_cursor_(std::declval<D const &>())))
516 -> decltype(view_adaptor::begin_cursor_(std::declval<D const &>()))
518 return view_adaptor::begin_cursor_(derived());
522 static constexpr adaptor_sentinel_t<D> end_cursor_(D & d) noexcept(noexcept(
523 adaptor_sentinel_t<D>{std::declval<detail::end_adaptor_t<D> &>().end(d),
524 range_access::end_adaptor(d)}))
526 auto adapt = range_access::end_adaptor(d);
527 auto pos = adapt.end(d);
528 return {std::move(pos), std::move(adapt)};
530 template(
typename D = Derived)(
531 requires same_as<D, Derived>)
532 constexpr
auto end_cursor() noexcept(
533 noexcept(view_adaptor::end_cursor_(std::declval<D &>())))
534 -> decltype(view_adaptor::end_cursor_(std::declval<D &>()))
536 return view_adaptor::end_cursor_(derived());
538 template(
typename D = Derived)(
539 requires same_as<D, Derived> AND range<base_range_t const>)
540 constexpr
auto end_cursor()
const noexcept(
541 noexcept(view_adaptor::end_cursor_(std::declval<D const &>())))
542 -> decltype(view_adaptor::end_cursor_(std::declval<D const &>()))
544 return view_adaptor::end_cursor_(derived());
557 : rng_(views::all(
static_cast<BaseRng &&
>(rng)))
559 constexpr base_range_t & base() noexcept
564 constexpr base_range_t
const &
base() const noexcept
573 #include <range/v3/detail/epilogue.hpp>
meta::if_c< std::is_reference< R >::value, meta::_t< std::remove_reference< R > > &&, detail::decay_t< R > > move_t
Definition: move.hpp:59
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
typename T::type _t
Type alias for T::type.
Definition: meta.hpp:141
bool_< 0==size< L >::type::value > empty
An Boolean integral constant wrapper around true if L is an empty type list; false,...
Definition: meta.hpp:2231
Definition: adaptor.hpp:110
Definition: adaptor.hpp:242
Definition: adaptor.hpp:234
Definition: adaptor.hpp:181
Definition: basic_iterator.hpp:47
Definition: adaptor.hpp:475
constexpr base_range_t const & base() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: adaptor.hpp:564
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition: facade.hpp:66