15#ifndef RANGES_V3_VIEW_ANY_VIEW_HPP
16#define RANGES_V3_VIEW_ANY_VIEW_HPP
28#include <range/v3/utility/addressof.hpp>
33#include <range/v3/detail/prologue.hpp>
36RANGES_DIAGNOSTIC_IGNORE_INCONSISTENT_OVERRIDE
37RANGES_DIAGNOSTIC_SUGGEST_OVERRIDE
59 constexpr category operator&(category lhs, category rhs)
noexcept
61 return static_cast<category
>(
66 constexpr category operator|(category lhs, category rhs)
noexcept
73 constexpr category operator^(category lhs, category rhs)
noexcept
80 constexpr category operator~(category lhs)
noexcept
83 ~static_cast<meta::_t<std::underlying_type<category>>>(lhs));
86 constexpr category & operator&=(category & lhs, category rhs)
noexcept
88 return (lhs = lhs & rhs);
91 constexpr category & operator|=(category & lhs, category rhs)
noexcept
93 return (lhs = lhs | rhs);
96 constexpr category & operator^=(category & lhs, category rhs)
noexcept
98 return (lhs = lhs ^ rhs);
104 template<
typename Rng>
105 constexpr category get_categories() noexcept
107 return (input_range<Rng> ? category::input :
category::
none) |
126 constexpr any_ref(T & obj) noexcept
127 : obj_(detail::addressof(obj))
129 , info_(&
typeid(rtti_tag<T>))
133 T & get() const noexcept
135 RANGES_ASSERT(obj_ && info_ && *info_ ==
typeid(rtti_tag<T>));
136 return *
const_cast<T *
>(
static_cast<T
const volatile *
>(obj_));
140 void const volatile * obj_ =
nullptr;
142 std::type_info
const * info_ =
nullptr;
146 template<
typename Base>
147 struct cloneable : Base
150 virtual ~cloneable()
override =
default;
151 cloneable() =
default;
152 cloneable(cloneable
const &) =
delete;
153 cloneable & operator=(cloneable
const &) =
delete;
154 virtual std::unique_ptr<cloneable> clone()
const = 0;
160 template(
typename Rng,
typename Ref)(
161 concept (any_compatible_range_)(Rng, Ref),
162 convertible_to<range_reference_t<Rng>, Ref>
166 template<
typename Rng,
typename Ref>
167 CPP_concept any_compatible_range =
168 CPP_concept_ref(detail::any_compatible_range_, Rng, Ref);
171 template<
typename Rng,
typename =
void>
172 struct any_view_sentinel_impl
173 :
private box<sentinel_t<Rng>, any_view_sentinel_impl<Rng>>
176 using box_t =
typename any_view_sentinel_impl::box;
179 any_view_sentinel_impl() =
default;
180 any_view_sentinel_impl(Rng & rng)
181 : box_t(ranges::end(rng))
183 void init(Rng & rng)
noexcept
185 box_t::get() = ranges::end(rng);
187 sentinel_t<Rng>
const & get(Rng &)
const noexcept
193 template<
typename Rng>
194 struct any_view_sentinel_impl<
195 Rng,
meta::
void_<decltype(ranges::end(std::declval<Rng const &>()))>>
197 any_view_sentinel_impl() =
default;
198 any_view_sentinel_impl(Rng &)
noexcept
200 void init(Rng &)
noexcept
202 sentinel_t<Rng> get(Rng & rng)
const noexcept
204 return ranges::end(rng);
208 template<
typename Ref,
bool Sized = false>
209 struct any_input_view_interface
211 virtual ~any_input_view_interface() =
default;
212 virtual void init() = 0;
213 virtual bool done() = 0;
214 virtual Ref read()
const = 0;
215 virtual void next() = 0;
217 template<
typename Ref>
218 struct any_input_view_interface<Ref, true> : any_input_view_interface<Ref, false>
220 virtual std::size_t
size() = 0;
223 template<
typename Ref>
224 struct any_input_cursor
226 using single_pass = std::true_type;
228 any_input_cursor() =
default;
229 constexpr any_input_cursor(any_input_view_interface<Ref> & view) noexcept
230 : view_{detail::addressof(view)}
234 return view_->read();
240 bool equal(any_input_cursor
const &)
const noexcept
244 bool equal(default_sentinel_t)
const
246 return !view_ || view_->done();
250 any_input_view_interface<Ref> * view_ =
nullptr;
253 template<
typename Rng,
typename Ref,
bool Sized = false>
254 struct RANGES_EMPTY_BASES any_input_view_impl
255 : any_input_view_interface<Ref, Sized>
256 ,
private any_view_sentinel_impl<Rng>
258 CPP_assert(any_compatible_range<Rng, Ref>);
259 CPP_assert(!Sized || (
bool)sized_range<Rng>);
261 explicit any_input_view_impl(Rng rng)
262 : rng_{std::move(rng)}
264 any_input_view_impl(any_input_view_impl
const &) =
delete;
265 any_input_view_impl & operator=(any_input_view_impl
const &) =
delete;
268 using sentinel_box_t = any_view_sentinel_impl<Rng>;
270 virtual void init()
override
272 sentinel_box_t::init(rng_);
273 current_ = ranges::begin(rng_);
275 virtual bool done()
override
277 return current_ == sentinel_box_t::get(rng_);
279 virtual Ref read()
const override
283 virtual void next()
override
289 return static_cast<std::size_t
>(ranges::size(rng_));
292 RANGES_NO_UNIQUE_ADDRESS Rng rng_;
293 RANGES_NO_UNIQUE_ADDRESS iterator_t<Rng> current_{};
296 template<
typename Ref, category Cat = category::forward,
typename enable =
void>
297 struct any_cursor_interface;
299 template<
typename Ref, category Cat>
300 struct any_cursor_interface<
301 Ref, Cat,
meta::if_c<(Cat & category::mask) == category::forward>>
303 virtual ~any_cursor_interface() =
default;
304 virtual any_ref iter()
306 virtual Ref read()
const = 0;
307 virtual bool equal(any_cursor_interface
const &)
const = 0;
308 virtual void next() = 0;
311 template<
typename Ref, category Cat>
312 struct any_cursor_interface<
313 Ref, Cat,
meta::if_c<(Cat & category::mask) == category::bidirectional>>
314 : any_cursor_interface<Ref, (Cat & ~category::mask) | category::forward>
316 virtual void prev() = 0;
319 template<
typename Ref, category Cat>
320 struct any_cursor_interface<
321 Ref, Cat,
meta::if_c<(Cat & category::mask) == category::random_access>>
322 : any_cursor_interface<Ref, (Cat & ~category::mask) | category::bidirectional>
324 virtual void advance(std::ptrdiff_t) = 0;
325 virtual std::ptrdiff_t distance_to(any_cursor_interface
const &)
const = 0;
328 template<
typename Ref, category Cat>
329 using any_cloneable_cursor_interface = cloneable<any_cursor_interface<Ref, Cat>>;
331 template<
typename I,
typename Ref, category Cat>
332 struct any_cursor_impl : any_cloneable_cursor_interface<Ref, Cat>
334 CPP_assert(convertible_to<iter_reference_t<I>, Ref>);
335 CPP_assert((Cat & category::forward) == category::forward);
337 any_cursor_impl() =
default;
338 any_cursor_impl(I it)
344 any_cursor_interface<Ref, (Cat & ~category::mask) | category::forward>;
348 any_ref iter()
const override
352 Ref read()
const override
356 bool equal(Forward
const & that_)
const override
358 auto & that = polymorphic_downcast<any_cursor_impl const &>(that_);
359 return that.it_ == it_;
365 std::unique_ptr<any_cloneable_cursor_interface<Ref, Cat>> clone()
368 return detail::make_unique<any_cursor_impl>(it_);
374 void advance(std::ptrdiff_t n)
378 std::ptrdiff_t distance_to(
379 any_cursor_interface<Ref, Cat>
const & that_)
const
381 auto & that = polymorphic_downcast<any_cursor_impl const &>(that_);
382 return static_cast<std::ptrdiff_t
>(that.it_ - it_);
386 struct fully_erased_view
392 ~fully_erased_view() =
default;
397 any_sentinel() =
default;
398 constexpr explicit any_sentinel(fully_erased_view & view) noexcept
403 template<
typename, category>
404 friend struct any_cursor;
406 fully_erased_view * view_ =
nullptr;
409 template<
typename Ref, category Cat>
413 CPP_assert((Cat & category::forward) == category::forward);
415 std::unique_ptr<any_cloneable_cursor_interface<Ref, Cat>> ptr_;
417 template<
typename Rng>
418 using impl_t = any_cursor_impl<iterator_t<Rng>, Ref, Cat>;
421 any_cursor() =
default;
422 template(
typename Rng)(
423 requires (!same_as<detail::decay_t<Rng>, any_cursor>) AND
424 forward_range<Rng> AND
425 any_compatible_range<Rng, Ref>)
426 explicit any_cursor(Rng && rng)
427 : ptr_{detail::make_unique<impl_t<Rng>>(begin(rng))}
429 any_cursor(any_cursor &&) =
default;
430 any_cursor(any_cursor
const & that)
431 : ptr_{that.ptr_ ? that.ptr_->clone() : nullptr}
433 any_cursor & operator=(any_cursor &&) =
default;
434 any_cursor & operator=(any_cursor
const & that)
436 ptr_ = (that.ptr_ ? that.ptr_->clone() :
nullptr);
444 bool equal(any_cursor
const & that)
const
446 RANGES_EXPECT(!ptr_ == !that.ptr_);
447 return !ptr_ || ptr_->equal(*that.ptr_);
449 bool equal(any_sentinel
const & that)
const
451 RANGES_EXPECT(!ptr_ == !that.view_);
452 return !ptr_ || that.view_->at_end(ptr_->iter());
462 requires (category::bidirectional == (Cat & category::bidirectional)))
468 auto advance(std::ptrdiff_t n)
470 requires (category::random_access == (Cat & category::random_access)))
476 auto distance_to(any_cursor
const & that)
const
477 -> CPP_ret(std::ptrdiff_t)(
478 requires (category::random_access == (Cat & category::random_access)))
480 RANGES_EXPECT(!ptr_ == !that.ptr_);
481 return !ptr_ ? 0 : ptr_->distance_to(*that.ptr_);
485 template<
typename Ref,
category Cat,
486 bool = (Cat & category::sized) == category::sized>
487 struct any_view_interface : fully_erased_view
489 CPP_assert((Cat & category::forward) == category::forward);
491 virtual ~any_view_interface() =
default;
492 virtual any_cursor<Ref, Cat> begin_cursor() = 0;
494 template<
typename Ref, category Cat>
495 struct any_view_interface<Ref, Cat, true> : any_view_interface<Ref, Cat, false>
497 virtual std::size_t
size() = 0;
500 template<
typename Ref, category Cat>
501 using any_cloneable_view_interface = cloneable<any_view_interface<Ref, Cat>>;
503 template<
typename Rng,
typename Ref, category Cat>
504 struct RANGES_EMPTY_BASES any_view_impl
505 : any_cloneable_view_interface<Ref, Cat>
506 ,
private box<Rng, any_view_impl<Rng, Ref, Cat>>
507 ,
private any_view_sentinel_impl<Rng>
509 CPP_assert((Cat & category::forward) == category::forward);
510 CPP_assert(any_compatible_range<Rng, Ref>);
511 CPP_assert((Cat & category::sized) == category::none ||
512 (
bool)sized_range<Rng>);
514 any_view_impl() =
default;
515 any_view_impl(Rng rng)
516 : range_box_t{std::move(rng)}
517 , sentinel_box_t{range_box_t::get()}
522 using range_box_t = box<Rng, any_view_impl>;
523 using sentinel_box_t = any_view_sentinel_impl<Rng>;
525 any_cursor<Ref, Cat> begin_cursor()
override
527 return any_cursor<Ref, Cat>{range_box_t::get()};
529 bool at_end(any_ref it_)
override
531 auto & it = it_.get<iterator_t<Rng>
const>();
532 return it == sentinel_box_t::get(range_box_t::get());
534 std::unique_ptr<any_cloneable_view_interface<Ref, Cat>> clone()
const override
536 return detail::make_unique<any_view_impl>(range_box_t::get());
540 return static_cast<std::size_t
>(ranges::size(range_box_t::get()));
548 template<
typename Ref, category Cat = category::input,
typename enable =
void>
551 (Cat & category::sized) == category::sized ? finite : unknown>
554 CPP_assert((Cat & category::forward) == category::forward);
557 template(
typename Rng)(
559 (!same_as<detail::decay_t<Rng>,
any_view>) AND
561 detail::any_compatible_range<Rng, Ref>)
563 :
any_view(
static_cast<Rng &&
>(rng),
564 meta::bool_<(get_categories<Rng>() & Cat) == Cat>{})
568 : ptr_{that.ptr_ ? that.ptr_->clone() :
nullptr}
573 ptr_ = (that.ptr_ ? that.ptr_->clone() :
nullptr);
579 -> CPP_ret(std::size_t)(
580 requires (category::sized == (Cat & category::sized)))
582 return ptr_ ? ptr_->size() : 0;
586 template<
typename Rng>
587 using impl_t = detail::any_view_impl<views::all_t<Rng>, Ref, Cat>;
588 template<
typename Rng>
589 any_view(Rng && rng, std::true_type)
590 : ptr_{detail::make_unique<impl_t<Rng>>(views::all(
static_cast<Rng &&
>(rng)))}
592 template<
typename Rng>
596 (get_categories<Rng>() & Cat) == Cat,
597 "The range passed to any_view() does not model the requested category");
600 detail::any_cursor<Ref, Cat> begin_cursor()
602 return ptr_ ? ptr_->begin_cursor() : detail::value_init{};
604 detail::any_sentinel end_cursor()
noexcept
606 return detail::any_sentinel{*ptr_};
609 std::unique_ptr<detail::any_cloneable_view_interface<Ref, Cat>> ptr_;
613 template<
typename Ref, category Cat>
614 struct any_view<Ref, Cat,
meta::if_c<(Cat & category::forward) == category::input>>
616 (Cat & category::sized) == category::sized ? finite : unknown>
621 template(
typename Rng)(
623 (!same_as<detail::decay_t<Rng>,
any_view>) AND
625 detail::any_compatible_range<Rng, Ref>)
627 : ptr_{std::make_shared<impl_t<Rng>>(views::all(
static_cast<Rng &&
>(rng)))}
632 -> CPP_ret(std::size_t)(
633 requires (category::sized == (Cat & category::sized)))
635 return ptr_ ? ptr_->size() : 0;
639 template<
typename Rng>
641 detail::any_input_view_impl<views::all_t<Rng>, Ref,
642 (Cat & category::sized) == category::sized>;
644 detail::any_input_cursor<Ref> begin_cursor()
650 return detail::any_input_cursor<Ref>{*ptr_};
653 std::shared_ptr<detail::any_input_view_interface<Ref, (Cat & category::sized) ==
658#if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
659 template(
typename Rng)(
662 ->any_view<range_reference_t<Rng>, get_categories<Rng>()>;
665 template<
typename Ref>
666 using any_input_view RANGES_DEPRECATED(
669 template<
typename Ref>
670 using any_forward_view RANGES_DEPRECATED(
671 "Use any_view<Ref, category::forward> instead.") =
674 template<
typename Ref>
675 using any_bidirectional_view RANGES_DEPRECATED(
676 "Use any_view<Ref, category::bidirectional> instead.") =
679 template<
typename Ref>
680 using any_random_access_view RANGES_DEPRECATED(
681 "Use any_view<Ref, category::random_access> instead.") =
685#include <range/v3/detail/satisfy_boost_range.hpp>
690#include <range/v3/detail/epilogue.hpp>
category
An enum that denotes the supported subset of range concepts supported by a range.
Definition any_view.hpp:44
@ sized
satisfies ranges::concepts::sized_range
@ random_access
satisfies ranges::concepts::random_access_range
@ forward
satisfies ranges::concepts::forward_range
@ input
satisfies ranges::concepts::input_range
@ bidirectional
satisfies ranges::concepts::bidirectional_range
@ mask
Mask away any properties other than iterator category.
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
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition meta.hpp:1696
void void_
An alias for void.
Definition meta.hpp:597
A type-erased view.
Definition any_view.hpp:552
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition facade.hpp:66