From 65677879cdf4e678d5cdeec7db2462577934e738 Mon Sep 17 00:00:00 2001 From: Hui Date: Fri, 31 May 2024 11:36:06 +0100 Subject: [PATCH] type erasure impl --- impl/any_view/any_view.hpp | 700 +-------------------------- impl/any_view/any_view_te.hpp | 729 +++++++++++++++++++++++++++++ impl/any_view/any_view_virtual.hpp | 700 +++++++++++++++++++++++++++ 3 files changed, 1434 insertions(+), 695 deletions(-) create mode 100644 impl/any_view/any_view_te.hpp create mode 100644 impl/any_view/any_view_virtual.hpp diff --git a/impl/any_view/any_view.hpp b/impl/any_view/any_view.hpp index 42d9484..1a90a59 100644 --- a/impl/any_view/any_view.hpp +++ b/impl/any_view/any_view.hpp @@ -1,700 +1,10 @@ #ifndef LIBCPP__RANGE_ANY_VIEW_HPP #define LIBCPP__RANGE_ANY_VIEW_HPP -#include -#include -#include -#include -namespace std::ranges { - -inline namespace __any_view { - -enum class category { - none = 0, - input = 1, - forward = 3, - bidirectional = 7, - random_access = 15, - contiguous = 31, - category_mask = contiguous, - sized = 32, - borrowed = 64, - common = 128, - move_only_view = 256 -}; - -constexpr category operator&(category lhs, category rhs) noexcept { - return static_cast( - static_cast>(lhs) & - static_cast>(rhs)); -} - -constexpr category operator|(category lhs, category rhs) noexcept { - return static_cast( - static_cast>(lhs) | - static_cast>(rhs)); -} - -constexpr auto operator<=>(category lhs, category rhs) noexcept { - return static_cast>(lhs) <=> - static_cast>(rhs); -} - -} // namespace __any_view - -template , - class RValueRef = add_rvalue_reference_t, - class Diff = ptrdiff_t> -class any_view { - public: - // "requires" is not allowed to use with virtual functions. - // so it looks complicated - template - struct iterator_interface; - - struct basic_input_iterator_interface { - constexpr virtual ~basic_input_iterator_interface() = default; - - constexpr virtual std::unique_ptr - move() = 0; - - constexpr virtual Ref deref() const = 0; - constexpr virtual void increment() = 0; - - constexpr virtual RValueRef iter_move() const = 0; - }; - - struct common_input_iterator : basic_input_iterator_interface { - constexpr virtual std::unique_ptr clone() const = 0; - constexpr virtual bool equal(const common_input_iterator &) const = 0; - }; - - template <> - struct iterator_interface - : std::conditional_t<(Cat & category::common) != category::none, - common_input_iterator, - basic_input_iterator_interface> {}; - - template <> - struct iterator_interface - : basic_input_iterator_interface { - iterator_interface() = default; - constexpr virtual std::unique_ptr clone() const = 0; - - constexpr virtual bool equal(const iterator_interface &) const = 0; - }; - - template <> - struct iterator_interface - : iterator_interface { - constexpr virtual void decrement() = 0; - }; - - template <> - struct iterator_interface - : iterator_interface { - constexpr virtual void advance(Diff) = 0; - constexpr virtual Diff distance_to(const iterator_interface &) const = 0; - }; - - using any_iter_interface = iterator_interface; - template - struct iterator_impl : any_iter_interface { - constexpr explicit iterator_impl(Iter tt) : it(std::move(tt)) {} - - // input - constexpr std::unique_ptr move() { - return std::make_unique(std::move(it)); - } - - constexpr Ref deref() const { return *it; }; - constexpr void increment() { ++it; }; - - constexpr RValueRef iter_move() const { - return std::ranges::iter_move(it); - }; - - // note: the following functions should ideally be constrained - // but requires is not allowed in virtual functions - - // forward - - iterator_impl() = default; - - using common_interface = std::conditional_t< - std::is_base_of_v, - common_input_iterator, iterator_interface>; - - constexpr virtual std::unique_ptr clone() const { - if constexpr ((Cat & category::category_mask) >= category::forward || - (Cat & category::common) != category::none) { - return std::make_unique(it); - } else { - assert(false); - return nullptr; - } - } - - constexpr bool equal(const common_interface &other) const { - if constexpr ((Cat & category::category_mask) >= category::forward || - (Cat & category::common) != category::none) { - return it == static_cast(other).it; - } else { - assert(false); - return false; - } - } - - // bidi - - constexpr void decrement() { - if constexpr ((Cat & category::category_mask) >= - category::bidirectional) { - --it; - } else { - assert(false); - } - } - - // random access - - constexpr void advance(Diff diff) { - if constexpr ((Cat & category::category_mask) >= - category::random_access) { - it += diff; - } else { - assert(false); - } - } - - constexpr Diff distance_to(const any_iter_interface &other) const { - if constexpr ((Cat & category::category_mask) >= - category::random_access) { - return Diff(it - static_cast(other).it); - } else { - assert(false); - return Diff{}; - } - } - - Iter it; - }; - - struct singular_impl : any_iter_interface { - singular_impl() = default; - - constexpr std::unique_ptr move() { - return std::make_unique(); - } - - constexpr Ref deref() const { assert(false); }; - constexpr void increment() { assert(false); }; - - constexpr RValueRef iter_move() const { assert(false); }; - - using common_interface = std::conditional_t< - std::is_base_of_v, - common_input_iterator, iterator_interface>; - - constexpr virtual std::unique_ptr clone() const { - return std::make_unique(); - } - - constexpr bool equal(const common_interface &other) const { - return dynamic_cast(&other) != nullptr; - } - - // bidi - constexpr void decrement() { assert(false); } - - // random access - - constexpr void advance(Diff) { assert(false); } - constexpr Diff distance_to(const any_iter_interface &) const { - assert(false); - return Diff{}; - } - }; - - struct empty_iterator_category {}; - struct with_iterator_category { - private: - constexpr static auto get_category() { - constexpr auto cat_mask = Cat & category::category_mask; - if constexpr (!std::is_reference_v) { - return std::input_iterator_tag{}; - } else if constexpr (cat_mask >= category::random_access) { - return std::random_access_iterator_tag{}; - } else if constexpr (cat_mask == category::bidirectional) { - return std::bidirectional_iterator_tag{}; - } else if constexpr (cat_mask == category::forward) { - return std::forward_iterator_tag{}; - } else { - return std::input_iterator_tag{}; - } - } - - public: - using iterator_category = decltype(get_category()); - }; - constexpr static auto get_concept() { - constexpr auto cat_mask = Cat & category::category_mask; - if constexpr (cat_mask >= category::random_access) { - return std::random_access_iterator_tag{}; - } else if constexpr (cat_mask == category::bidirectional) { - return std::bidirectional_iterator_tag{}; - } else if constexpr (cat_mask == category::forward) { - return std::forward_iterator_tag{}; - } else { - return std::input_iterator_tag{}; - } - } - struct any_iterator - : std::conditional_t<(Cat & category::category_mask) >= category::forward, - with_iterator_category, empty_iterator_category> { - using iterator_concept = decltype(get_concept()); - using value_type = Value; - using difference_type = Diff; - - constexpr any_iterator() : impl_(std::make_unique()) {} - - template - consteval static bool category_constraint() { - constexpr auto cat_mask = Cat & category::category_mask; - if constexpr (cat_mask == category::contiguous) { - return std::contiguous_iterator; - } else if constexpr (cat_mask == category::random_access) { - return std::random_access_iterator; - } else if constexpr (cat_mask == category::bidirectional) { - return std::bidirectional_iterator; - } else if constexpr (cat_mask == category::forward) { - return std::forward_iterator; - } else { - return std::input_iterator; - } - } - - template - requires(!std::same_as && category_constraint()) - constexpr any_iterator(Iter iter) - : impl_(std::make_unique>(std::move(iter))) {} - - // TODO: do we allow copy for input iterator and how? - constexpr any_iterator(const any_iterator &other) - requires((Cat & category::category_mask) >= category::forward || - (Cat & category::common) != category::none) - { - impl_ = cast_unique_ptr(other.impl_->clone()); - } - - constexpr any_iterator(any_iterator &&other) { - impl_ = cast_unique_ptr(other.impl_->move()); - } - - constexpr any_iterator &operator=(const any_iterator &other) - requires((Cat & category::category_mask) >= category::forward || - (Cat & category::common) != category::none) - { - if (this != &other) { - impl_ = cast_unique_ptr(other.impl_->clone()); - } - return *this; - } - - constexpr any_iterator &operator=(any_iterator &&other) { - if (this != &other) { - impl_ = cast_unique_ptr(other.impl_->move()); - } - return *this; - } - - constexpr Ref operator*() const { return impl_->deref(); } - - constexpr any_iterator &operator++() { - impl_->increment(); - return *this; - } - - constexpr void operator++(int) { ++(*this); } - - constexpr any_iterator operator++(int) - requires((Cat & category::category_mask) >= category::forward) - { - auto tmp = *this; - ++(*this); - return tmp; - } - - constexpr any_iterator &operator--() - requires((Cat & category::category_mask) >= category::bidirectional) - { - impl_->decrement(); - return *this; - } - - constexpr any_iterator operator--(int) - requires((Cat & category::category_mask) >= category::bidirectional) - { - auto tmp = *this; - --(*this); - return tmp; - } - - constexpr any_iterator &operator+=(difference_type n) - requires((Cat & category::category_mask) >= category::random_access) - { - impl_->advance(n); - return *this; - } - - constexpr any_iterator &operator-=(difference_type n) - requires((Cat & category::category_mask) >= category::random_access) - { - *this += -n; - return *this; - } - - constexpr Ref operator[](difference_type n) const - requires((Cat & category::category_mask) >= category::random_access) - { - return *((*this) + n); - } - - friend constexpr bool operator<(const any_iterator &x, - const any_iterator &y) - requires((Cat & category::category_mask) >= category::random_access) - { - return (x - y) < 0; - } - - friend constexpr bool operator>(const any_iterator &x, - const any_iterator &y) - requires((Cat & category::category_mask) >= category::random_access) - { - return (x - y) > 0; - } - - friend constexpr bool operator<=(const any_iterator &x, - const any_iterator &y) - requires((Cat & category::category_mask) >= category::random_access) - { - return (x - y) <= 0; - } - - friend constexpr bool operator>=(const any_iterator &x, - const any_iterator &y) - requires((Cat & category::category_mask) >= category::random_access) - { - return (x - y) >= 0; - } - - friend constexpr any_iterator operator+(const any_iterator &it, - difference_type n) - requires((Cat & category::category_mask) >= category::random_access) - { - auto temp = it; - temp += n; - return temp; - } - - friend constexpr any_iterator operator+(difference_type n, - const any_iterator &it) - requires((Cat & category::category_mask) >= category::random_access) - { - return it + n; - } - - friend constexpr any_iterator operator-(const any_iterator &it, - difference_type n) - requires((Cat & category::category_mask) >= category::random_access) - { - auto temp = it; - temp -= n; - return temp; - } - - friend constexpr difference_type operator-(const any_iterator &x, - const any_iterator &y) - requires((Cat & category::category_mask) >= category::random_access) - { - return x.impl_->distance_to(*(y.impl_)); - } - - friend constexpr bool operator==(const any_iterator &x, - const any_iterator &y) - requires((Cat & category::category_mask) >= category::forward || - (Cat & category::common) != category::none) - { - return x.impl_->equal(*(y.impl_)); - } - - friend constexpr RValueRef iter_move(const any_iterator &iter) { - return iter.impl_->iter_move(); - } - - constexpr any_iter_interface const &get_impl() const { return *impl_; } - - private: - std::unique_ptr impl_; - - constexpr any_iterator(std::unique_ptr &&impl) - : impl_(std::move(impl)) {} - - template - constexpr static std::unique_ptr cast_unique_ptr( - std::unique_ptr &&p) { - return std::unique_ptr( - static_cast(p.release())); - } - }; - - using iterator = std::conditional_t<(Cat & category::category_mask) == - category::contiguous, - std::add_pointer_t, any_iterator>; - struct any_sentinel_interface { - constexpr virtual std::unique_ptr move() = 0; - - constexpr virtual std::unique_ptr clone() const = 0; - - constexpr virtual ~any_sentinel_interface() = default; - - constexpr virtual bool equal(const iterator &) const = 0; - }; - - template - struct sentinel_impl : any_sentinel_interface { - constexpr explicit sentinel_impl(Sent st) : st_(std::move(st)) {} - constexpr std::unique_ptr move() override { - return std::make_unique(std::move(st_)); - } - - constexpr std::unique_ptr clone() const override { - return std::make_unique(st_); - } - - constexpr bool equal(const iterator &iter) const override { - if constexpr ((Cat & category::category_mask) == category::contiguous) { - return st_ == iter; - } else { - if (auto iter_impl = - dynamic_cast const *>(&iter.get_impl())) { - return iter_impl->it == st_; - } - } - return false; - } - - private: - Sent st_; - }; - - struct any_sentinel { - constexpr any_sentinel() = default; - - template - struct tag {}; - - template - constexpr any_sentinel(Sent sent, tag) - : impl_(std::make_unique>(std::move(sent))) {} - - constexpr any_sentinel(const any_sentinel &other) { - if (other.impl_) { - impl_ = other.impl_->clone(); - } - } - - constexpr any_sentinel(any_sentinel &&other) { - if (other.impl_) { - impl_ = other.impl_->move(); - } - } - - constexpr any_sentinel &operator=(const any_sentinel &other) { - if (this != &other) { - impl_ = other.impl_ ? other.impl_->clone() : other.impl_; - } - return *this; - } - - constexpr any_sentinel &operator=(any_sentinel &&other) { - if (this != &other) { - impl_ = other.impl_ ? other.impl_->move() : other.impl_; - } - return *this; - } - - friend constexpr bool operator==(const iterator &iter, - const any_sentinel &sent) { - if (!sent.impl_) return false; - return sent.impl_->equal(iter); - } - - private: - std::unique_ptr impl_ = nullptr; - - constexpr any_sentinel(std::unique_ptr &&impl) - : impl_(std::move(impl)) {} - }; - - using sentinel = - std::conditional_t<(Cat & category::common) == category::none, - any_sentinel, iterator>; - - struct sized_interface { - constexpr virtual std::size_t size() const = 0; - }; - - template - struct clonable_interface { - constexpr virtual std::unique_ptr clone() const = 0; - }; - - template - struct basic_any_view_interface { - constexpr virtual std::unique_ptr move() = 0; - - constexpr virtual iterator begin() = 0; - constexpr virtual sentinel end() = 0; - - constexpr virtual ~basic_any_view_interface() = default; - }; - - struct any_view_interface : basic_any_view_interface, - sized_interface, - clonable_interface {}; - - template - struct any_view_impl : any_view_interface { - constexpr explicit any_view_impl(View view) : view_(std::move(view)) {} - - constexpr std::unique_ptr move() override { - return std::make_unique(std::move(view_)); - } - - constexpr std::unique_ptr clone() const override { - if constexpr ((Cat & category::move_only_view) == category::none) { - return std::make_unique(view_); - } else { - assert(false); - return nullptr; - } - } - - constexpr iterator begin() override { - if constexpr ((Cat & category::category_mask) == category::contiguous) { - return std::ranges::begin(view_); - } else { - return any_iterator(std::ranges::begin(view_)); - } - } - - constexpr sentinel end() override { - if constexpr ((Cat & category::category_mask) == category::contiguous && - (Cat & category::common) != category::none) { - return std::ranges::end(view_); - } else if constexpr ((Cat & category::common) != category::none) { - return any_iterator(std::ranges::end(view_)); - } else { - using tag_t = any_sentinel::template tag>; - return any_sentinel(std::ranges::end(view_), tag_t{}); - } - } - - constexpr std::size_t size() const override { - if constexpr ((Cat & category::sized) != category::none) { - return std::ranges::size(view_); - } else { - assert(false); - return 0; - } - } - - private: - View view_; - }; - - template - consteval static bool view_category_constraint() { - if constexpr ((Cat & category::sized) != category::none && - !std::ranges::sized_range) { - return false; - } - - if constexpr ((Cat & category::common) != category::none && - !std::ranges::common_range) { - return false; - } - - if constexpr ((Cat & category::borrowed) != category::none && - !std::ranges::borrowed_range) { - return false; - } - - if constexpr ((Cat & category::move_only_view) == category::none && - !std::copyable) { - return false; - } - constexpr auto cat_mask = Cat & category::category_mask; - if constexpr (cat_mask == category::contiguous) { - return std::ranges::contiguous_range; - } else if constexpr (cat_mask == category::random_access) { - return std::ranges::random_access_range; - } else if constexpr (cat_mask == category::bidirectional) { - return std::ranges::bidirectional_range; - } else if constexpr (cat_mask == category::forward) { - return std::ranges::forward_range; - } else { - return std::ranges::input_range; - } - } - - template - requires(!std::same_as && std::ranges::view && - view_category_constraint()) - constexpr any_view(View view) - : impl_(std::make_unique>(std::move(view))) {} - - constexpr any_view(const any_view &other) - requires((Cat & category::move_only_view) == category::none) - : impl_(other.impl_->clone()) {} - - constexpr any_view(any_view &&other) : impl_(other.impl_->move()) {} - - constexpr any_view &operator=(const any_view &other) - requires((Cat & category::move_only_view) == category::none) - { - if (this != &other) { - impl_ = other.impl_->clone(); - } - return *this; - } - - constexpr any_view &operator=(any_view &&other) { - if (this != &other) { - impl_ = other.impl_->move(); - } - return *this; - } - - constexpr iterator begin() { return impl_->begin(); } - constexpr sentinel end() { return impl_->end(); } - - constexpr std::size_t size() const - requires((Cat & category::sized) != category::none) - { - return impl_->size(); - } - - private: - std::unique_ptr impl_; -}; - -template -inline constexpr bool - enable_borrowed_range> = - (Cat & category::borrowed) != category::none; - -} // namespace std::ranges +#if 1 +#include "any_view_te.hpp" +#else +#include "any_view_virtual.hpp" +#endif #endif diff --git a/impl/any_view/any_view_te.hpp b/impl/any_view/any_view_te.hpp new file mode 100644 index 0000000..5c386ae --- /dev/null +++ b/impl/any_view/any_view_te.hpp @@ -0,0 +1,729 @@ +#ifndef LIBCPP__RANGE_ANY_VIEW_TE_HPP +#define LIBCPP__RANGE_ANY_VIEW_TE_HPP + +#include +#include +#include +#include +namespace std::ranges { + +inline namespace __any_view { + +enum class category { + none = 0, + input = 1, + forward = 3, + bidirectional = 7, + random_access = 15, + contiguous = 31, + category_mask = contiguous, + sized = 32, + borrowed = 64, + common = 128, + move_only_view = 256 +}; + +constexpr category operator&(category lhs, category rhs) noexcept { + return static_cast( + static_cast>(lhs) & + static_cast>(rhs)); +} + +constexpr category operator|(category lhs, category rhs) noexcept { + return static_cast( + static_cast>(lhs) | + static_cast>(rhs)); +} + +constexpr auto operator<=>(category lhs, category rhs) noexcept { + return static_cast>(lhs) <=> + static_cast>(rhs); +} + +} // namespace __any_view + +template , + class RValueRef = add_rvalue_reference_t, + class Diff = ptrdiff_t> +class any_view { + public: + struct any_iterator; + struct any_sentinel; + + template + struct maybe_t : T {}; + + template + struct maybe_t {}; + + struct destructor_vtable { + void (*destructor_)(void *); + }; + + struct movable_vtable { + void *(*move_)(void *); + }; + + struct copyable_vtable { + void *(*copy_)(const void *); + }; + + template + struct iterator_vtable; + + struct basic_input_iterator_vtable : destructor_vtable, movable_vtable { + Ref (*deref_)(const void *); + void (*increment_)(void *); + RValueRef (*iter_move_)(const void *); + }; + + struct equality_vtable { + bool (*equal_)(const void *, const void *); + }; + + struct common_input_iterator : basic_input_iterator_vtable, + copyable_vtable, + equality_vtable {}; + + template <> + struct iterator_vtable + : std::conditional_t<(Cat & category::common) != category::none, + common_input_iterator, basic_input_iterator_vtable> { + }; + + template <> + struct iterator_vtable + : basic_input_iterator_vtable, copyable_vtable, equality_vtable {}; + + template <> + struct iterator_vtable + : iterator_vtable { + void (*decrement_)(void *); + }; + + template <> + struct iterator_vtable + : iterator_vtable { + void (*advance_)(void *, Diff); + Diff (*distance_to_)(const void *, const void *); + }; + + // for contiguous , we just return raw pointers + template <> + struct iterator_vtable {}; + + using any_iterator_vtable = iterator_vtable; + + struct empty_iterator_category {}; + struct with_iterator_category { + private: + constexpr static auto get_category() { + constexpr auto cat_mask = Cat & category::category_mask; + if constexpr (!std::is_reference_v) { + return std::input_iterator_tag{}; + } else if constexpr (cat_mask >= category::random_access) { + return std::random_access_iterator_tag{}; + } else if constexpr (cat_mask == category::bidirectional) { + return std::bidirectional_iterator_tag{}; + } else if constexpr (cat_mask == category::forward) { + return std::forward_iterator_tag{}; + } else { + return std::input_iterator_tag{}; + } + } + + public: + using iterator_category = decltype(get_category()); + }; + constexpr static auto get_concept() { + constexpr auto cat_mask = Cat & category::category_mask; + if constexpr (cat_mask >= category::random_access) { + return std::random_access_iterator_tag{}; + } else if constexpr (cat_mask == category::bidirectional) { + return std::bidirectional_iterator_tag{}; + } else if constexpr (cat_mask == category::forward) { + return std::forward_iterator_tag{}; + } else { + return std::input_iterator_tag{}; + } + } + struct any_iterator + : std::conditional_t<(Cat & category::category_mask) >= category::forward, + with_iterator_category, empty_iterator_category> { + using iterator_concept = decltype(get_concept()); + using value_type = Value; + using difference_type = Diff; + + constexpr any_iterator() = default; + + constexpr any_iterator(const any_iterator &other) + requires((Cat & category::category_mask) >= category::forward || + (Cat & category::common) != category::none) + : parent_(other.parent_) { + if (!other.is_singular()) { + iter_ = (*(other.parent_->iter_vtable_.copy_))(other.iter_); + } + } + + constexpr any_iterator(any_iterator &&other) : parent_(other.parent_) { + if (!other.is_singular()) { + iter_ = (*(other.parent_->iter_vtable_.move_))(other.iter_); + } + } + + constexpr any_iterator &operator=(const any_iterator &other) + requires((Cat & category::category_mask) >= category::forward || + (Cat & category::common) != category::none) + { + if (this != &other) { + if (!is_singular()) { + (*(parent_->iter_vtable_.destructor_))(iter_); + } + if (!other.is_singular()) { + iter_ = (*(other.parent_->iter_vtable_.copy_))(other.iter_); + } + parent_ = other.parent_; + } + return *this; + } + + constexpr any_iterator &operator=(any_iterator &&other) { + if (this != &other) { + if (!is_singular()) { + (*(parent_->iter_vtable_.destructor_))(iter_); + } + if (!other.is_singular()) { + iter_ = (*(other.parent_->iter_vtable_.move_))(other.iter_); + } + parent_ = other.parent_; + } + return *this; + } + + constexpr ~any_iterator() { + if (!is_singular()) { + (*(parent_->iter_vtable_.destructor_))(iter_); + } + } + + constexpr Ref operator*() const { + assert(parent_); + return (*(parent_->iter_vtable_.deref_))(iter_); + } + + constexpr any_iterator &operator++() { + assert(parent_); + (*(parent_->iter_vtable_.increment_))(iter_); + return *this; + } + + constexpr void operator++(int) { ++(*this); } + + constexpr any_iterator operator++(int) + requires((Cat & category::category_mask) >= category::forward) + { + auto tmp = *this; + ++(*this); + return tmp; + } + + constexpr any_iterator &operator--() + requires((Cat & category::category_mask) >= category::bidirectional) + { + assert(parent_); + (*(parent_->iter_vtable_.decrement_))(iter_); + return *this; + } + + constexpr any_iterator operator--(int) + requires((Cat & category::category_mask) >= category::bidirectional) + { + auto tmp = *this; + --(*this); + return tmp; + } + + constexpr any_iterator &operator+=(difference_type n) + requires((Cat & category::category_mask) >= category::random_access) + { + assert(parent_); + (*(parent_->iter_vtable_.advance_))(iter_, n); + return *this; + } + + constexpr any_iterator &operator-=(difference_type n) + requires((Cat & category::category_mask) >= category::random_access) + { + *this += -n; + return *this; + } + + constexpr Ref operator[](difference_type n) const + requires((Cat & category::category_mask) >= category::random_access) + { + return *((*this) + n); + } + + friend constexpr bool operator<(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::random_access) + { + return (x - y) < 0; + } + + friend constexpr bool operator>(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::random_access) + { + return (x - y) > 0; + } + + friend constexpr bool operator<=(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::random_access) + { + return (x - y) <= 0; + } + + friend constexpr bool operator>=(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::random_access) + { + return (x - y) >= 0; + } + + friend constexpr any_iterator operator+(const any_iterator &it, + difference_type n) + requires((Cat & category::category_mask) >= category::random_access) + { + auto temp = it; + temp += n; + return temp; + } + + friend constexpr any_iterator operator+(difference_type n, + const any_iterator &it) + requires((Cat & category::category_mask) >= category::random_access) + { + return it + n; + } + + friend constexpr any_iterator operator-(const any_iterator &it, + difference_type n) + requires((Cat & category::category_mask) >= category::random_access) + { + auto temp = it; + temp -= n; + return temp; + } + + friend constexpr difference_type operator-(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::random_access) + { + assert(x.parent_); + assert(y.parent_); + assert(x.parent_ == y.parent_); + return (*(x.parent_->iter_vtable_.distance_to_))(x.iter_, y.iter_); + } + + friend constexpr bool operator==(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::forward || + (Cat & category::common) != category::none) + { + if (x.parent_ != y.parent_) return false; + if (!x.parent_) return true; + return (*(x.parent_->iter_vtable_.equal_))(x.iter_, y.iter_); + } + + friend constexpr RValueRef iter_move(const any_iterator &iter) { + assert(iter.parent_); + return (*(iter.parent_->iter_vtable_.iter_move_))(iter.iter_); + } + + // private: + any_view *parent_ = nullptr; + void *iter_ = nullptr; + + template + constexpr any_iterator(any_view *parent, Iter iter) + : parent_(parent), iter_(new Iter(std::move(iter))) {} + + constexpr bool is_singular() const { return !parent_; } + }; + + struct basic_vtable_gen { + template + static constexpr void *move(void *self) { + return new T(std::move(*(static_cast(self)))); + } + + template + static constexpr void *copy(const void *self) { + return new T(*(static_cast(self))); + } + + template + static constexpr void destroy(void *self) { + return std::destroy_at(static_cast(self)); + } + }; + + struct iterator_vtable_gen : basic_vtable_gen { + template + static constexpr auto generate() { + any_iterator_vtable t; + + if constexpr ((Cat & category::category_mask) != category::contiguous) { + t.move_ = &basic_vtable_gen::template move; + t.destructor_ = &basic_vtable_gen::template destroy; + t.deref_ = &deref; + t.increment_ = &increment; + t.iter_move_ = &iter_move; + + if constexpr ((Cat & category::category_mask) >= category::forward || + (Cat & category::common) != category::none) { + t.copy_ = &basic_vtable_gen::template copy; + t.equal_ = &equal; + } + + if constexpr ((Cat & category::category_mask) >= + category::bidirectional) { + t.decrement_ = &decrement; + } + + if constexpr ((Cat & category::category_mask) >= + category::random_access) { + t.advance_ = &advance; + t.distance_to_ = &distance_to; + } + } + return t; + } + + // input + + template + static constexpr Ref deref(const void *self) { + return **(static_cast(self)); + }; + + template + static constexpr void increment(void *self) { + ++(*(static_cast(self))); + }; + + template + static constexpr RValueRef iter_move(const void *self) { + return std::ranges::iter_move(*(static_cast(self))); + }; + + // forward + + template + static constexpr bool equal(const void *self, const void *other) { + return (*static_cast(self)) == + (*static_cast(other)); + } + + // bidi + + template + static constexpr void decrement(void *self) { + --(*(static_cast(self))); + } + + // random access + + template + static constexpr void advance(void *self, Diff diff) { + (*static_cast(self)) += diff; + } + + template + static constexpr Diff distance_to(const void *self, const void *other) { + return Diff((*static_cast(self)) - + (*static_cast(other))); + } + }; + + using iterator = std::conditional_t<(Cat & category::category_mask) == + category::contiguous, + std::add_pointer_t, any_iterator>; + + struct sentinel_vtable : movable_vtable, copyable_vtable, destructor_vtable { + bool (*equal_)(const iterator &, const any_sentinel &); + }; + + struct any_sentinel_vtable + : maybe_t {}; + + struct any_sentinel { + constexpr any_sentinel() = default; + + constexpr any_sentinel(const any_sentinel &other) : parent_(other.parent_) { + if (!other.is_singular()) { + sent_ = (*(other.parent_->sent_vtable_.copy_))(other.sent_); + } + } + + constexpr any_sentinel(any_sentinel &&other) : parent_(other.parent_) { + if (!other.is_singular()) { + sent_ = (*(other.parent_->sent_vtable_.move_))(other.sent_); + } + } + + constexpr any_sentinel &operator=(const any_sentinel &other) { + if (this != &other) { + if (!is_singular()) { + (*(parent_->sent_vtable_.destructor_))(sent_); + } + if (!other.is_singular()) { + sent_ = (*(other.parent_->sent_vtable_.copy_))(other.sent_); + } + parent_ = other.parent_; + } + return *this; + } + + constexpr any_sentinel &operator=(any_sentinel &&other) { + if (this != &other) { + if (!is_singular()) { + (*(parent_->sent_vtable_.destructor_))(sent_); + } + if (!other.is_singular()) { + sent_ = (*(other.parent_->sent_vtable_.move_))(other.sent_); + } + parent_ = other.parent_; + } + return *this; + } + + constexpr ~any_sentinel() { + if (!is_singular()) { + (*(parent_->sent_vtable_.destructor_))(sent_); + } + } + + friend constexpr bool operator==(const iterator &iter, + const any_sentinel &sent) { + return (*(sent.parent_->sent_vtable_.equal_))(iter, sent); + } + + // private: + any_view *parent_ = nullptr; + void *sent_ = nullptr; + + template + constexpr any_sentinel(any_view *parent, Sent sent) + : parent_(parent), sent_(new Sent(std::move(sent))) {} + + constexpr bool is_singular() const { return !parent_; } + }; + + using sentinel = + std::conditional_t<(Cat & category::common) == category::none, + any_sentinel, iterator>; + + struct sentinel_vtable_gen : basic_vtable_gen { + template + static constexpr auto generate() { + any_sentinel_vtable t; + + if constexpr ((Cat & category::common) == category::none) { + t.move_ = &basic_vtable_gen::template move; + t.copy_ = &basic_vtable_gen::template copy; + t.destructor_ = &basic_vtable_gen::template destroy; + t.equal_ = &equal; + } + + return t; + } + + template + static constexpr bool equal(const iterator &iter, + const any_sentinel &sent) { + if (sent.is_singular()) return false; + if constexpr ((Cat & category::category_mask) == category::contiguous) { + return iter == *static_cast(sent.sent_); + } else { + if (iter.is_singular()) return false; + return *static_cast(iter.iter_) == + *static_cast(sent.sent_); + } + } + }; + + struct sized_vtable { + std::size_t (*size_)(const void *); + }; + + struct view_vtable + : destructor_vtable, + movable_vtable, + maybe_t, + maybe_t { + iterator (*begin_)(any_view *); + sentinel (*end_)(any_view *); + }; + + struct view_vtable_gen : basic_vtable_gen { + template + static constexpr auto generate() { + view_vtable t; + t.move_ = &basic_vtable_gen::template move; + t.destructor_ = &basic_vtable_gen::template destroy; + + t.begin_ = &begin; + t.end_ = &end; + + if constexpr ((Cat & category::move_only_view) == category::none) { + t.copy_ = &basic_vtable_gen::template copy; + } + + if constexpr ((Cat & category::sized) != category::none) { + t.size_ = &size; + } + + return t; + } + + template + static constexpr iterator begin(any_view *av) { + auto &view = *(static_cast(av->view_)); + if constexpr ((Cat & category::category_mask) == category::contiguous) { + return std::ranges::begin(view); + } else { + return any_iterator(av, std::ranges::begin(view)); + } + } + + template + static constexpr sentinel end(any_view *av) { + auto &view = *(static_cast(av->view_)); + if constexpr ((Cat & category::category_mask) == category::contiguous && + (Cat & category::common) != category::none) { + return std::ranges::end(view); + } else if constexpr ((Cat & category::common) != category::none) { + return any_iterator(av, std::ranges::end(view)); + } else { + return any_sentinel(av, std::ranges::end(view)); + } + } + + template + static constexpr std::size_t size(const void *view) { + return std::ranges::size(*(static_cast(view))); + } + }; + + template + consteval static bool view_category_constraint() { + if constexpr ((Cat & category::sized) != category::none && + !std::ranges::sized_range) { + return false; + } + + if constexpr ((Cat & category::common) != category::none && + !std::ranges::common_range) { + return false; + } + + if constexpr ((Cat & category::borrowed) != category::none && + !std::ranges::borrowed_range) { + return false; + } + + if constexpr ((Cat & category::move_only_view) == category::none && + !std::copyable) { + return false; + } + constexpr auto cat_mask = Cat & category::category_mask; + if constexpr (cat_mask == category::contiguous) { + return std::ranges::contiguous_range; + } else if constexpr (cat_mask == category::random_access) { + return std::ranges::random_access_range; + } else if constexpr (cat_mask == category::bidirectional) { + return std::ranges::bidirectional_range; + } else if constexpr (cat_mask == category::forward) { + return std::ranges::forward_range; + } else { + return std::ranges::input_range; + } + } + + template + requires(!std::same_as && std::ranges::view && + view_category_constraint()) + constexpr any_view(View view) + : iter_vtable_(iterator_vtable_gen::template generate< + std::ranges::iterator_t>()), + sent_vtable_(sentinel_vtable_gen::template generate< + std::ranges::iterator_t, + std::ranges::sentinel_t>()), + view_vtable_(view_vtable_gen::template generate()), + view_(new View(std::move(view))) {} + + constexpr any_view(const any_view &other) + requires((Cat & category::move_only_view) == category::none) + : iter_vtable_(other.iter_vtable_), + sent_vtable_(other.sent_vtable_), + view_vtable_(other.view_vtable_), + view_((*(view_vtable_.copy_))(other.view_)) {} + + constexpr any_view(any_view &&other) + : iter_vtable_(other.iter_vtable_), + sent_vtable_(other.sent_vtable_), + view_vtable_(other.view_vtable_), + view_((*(view_vtable_.move_))(other.view_)) {} + + constexpr any_view &operator=(const any_view &other) + requires((Cat & category::move_only_view) == category::none) + { + if (this != &other) { + (*(view_vtable_.destructor_))(view_); + view_ = (*(other.view_vtable_.copy_))(other.view_); + iter_vtable_ = other.iter_vtable_; + sent_vtable_ = other.sent_vtable_; + view_vtable_ = other.view_vtable_; + } + return *this; + } + + constexpr any_view &operator=(any_view &&other) { + if (this != &other) { + (*(view_vtable_.destructor_))(view_); + view_ = (*(other.view_vtable_.move_))(other.view_); + iter_vtable_ = other.iter_vtable_; + sent_vtable_ = other.sent_vtable_; + view_vtable_ = other.view_vtable_; + } + return *this; + } + + constexpr iterator begin() { return (*(view_vtable_.begin_))(this); } + constexpr sentinel end() { return (*(view_vtable_.end_))(this); } + + constexpr std::size_t size() const + requires((Cat & category::sized) != category::none) + { + return (*(view_vtable_.size_))(view_); + } + + private: + any_iterator_vtable iter_vtable_; + any_sentinel_vtable sent_vtable_; + view_vtable view_vtable_; + void *view_; +}; + +template +inline constexpr bool + enable_borrowed_range> = + (Cat & category::borrowed) != category::none; + +} // namespace std::ranges + +#endif diff --git a/impl/any_view/any_view_virtual.hpp b/impl/any_view/any_view_virtual.hpp new file mode 100644 index 0000000..35cf247 --- /dev/null +++ b/impl/any_view/any_view_virtual.hpp @@ -0,0 +1,700 @@ +#ifndef LIBCPP__RANGE_ANY_VIEW_VIRTUAL_HPP +#define LIBCPP__RANGE_ANY_VIEW_VIRTUAL_HPP + +#include +#include +#include +#include +namespace std::ranges { + +inline namespace __any_view { + +enum class category { + none = 0, + input = 1, + forward = 3, + bidirectional = 7, + random_access = 15, + contiguous = 31, + category_mask = contiguous, + sized = 32, + borrowed = 64, + common = 128, + move_only_view = 256 +}; + +constexpr category operator&(category lhs, category rhs) noexcept { + return static_cast( + static_cast>(lhs) & + static_cast>(rhs)); +} + +constexpr category operator|(category lhs, category rhs) noexcept { + return static_cast( + static_cast>(lhs) | + static_cast>(rhs)); +} + +constexpr auto operator<=>(category lhs, category rhs) noexcept { + return static_cast>(lhs) <=> + static_cast>(rhs); +} + +} // namespace __any_view + +template , + class RValueRef = add_rvalue_reference_t, + class Diff = ptrdiff_t> +class any_view { + public: + // "requires" is not allowed to use with virtual functions. + // so it looks complicated + template + struct iterator_interface; + + struct basic_input_iterator_interface { + constexpr virtual ~basic_input_iterator_interface() = default; + + constexpr virtual std::unique_ptr + move() = 0; + + constexpr virtual Ref deref() const = 0; + constexpr virtual void increment() = 0; + + constexpr virtual RValueRef iter_move() const = 0; + }; + + struct common_input_iterator : basic_input_iterator_interface { + constexpr virtual std::unique_ptr clone() const = 0; + constexpr virtual bool equal(const common_input_iterator &) const = 0; + }; + + template <> + struct iterator_interface + : std::conditional_t<(Cat & category::common) != category::none, + common_input_iterator, + basic_input_iterator_interface> {}; + + template <> + struct iterator_interface + : basic_input_iterator_interface { + iterator_interface() = default; + constexpr virtual std::unique_ptr clone() const = 0; + + constexpr virtual bool equal(const iterator_interface &) const = 0; + }; + + template <> + struct iterator_interface + : iterator_interface { + constexpr virtual void decrement() = 0; + }; + + template <> + struct iterator_interface + : iterator_interface { + constexpr virtual void advance(Diff) = 0; + constexpr virtual Diff distance_to(const iterator_interface &) const = 0; + }; + + using any_iter_interface = iterator_interface; + template + struct iterator_impl : any_iter_interface { + constexpr explicit iterator_impl(Iter tt) : it(std::move(tt)) {} + + // input + constexpr std::unique_ptr move() { + return std::make_unique(std::move(it)); + } + + constexpr Ref deref() const { return *it; }; + constexpr void increment() { ++it; }; + + constexpr RValueRef iter_move() const { + return std::ranges::iter_move(it); + }; + + // note: the following functions should ideally be constrained + // but requires is not allowed in virtual functions + + // forward + + iterator_impl() = default; + + using common_interface = std::conditional_t< + std::is_base_of_v, + common_input_iterator, iterator_interface>; + + constexpr virtual std::unique_ptr clone() const { + if constexpr ((Cat & category::category_mask) >= category::forward || + (Cat & category::common) != category::none) { + return std::make_unique(it); + } else { + assert(false); + return nullptr; + } + } + + constexpr bool equal(const common_interface &other) const { + if constexpr ((Cat & category::category_mask) >= category::forward || + (Cat & category::common) != category::none) { + return it == static_cast(other).it; + } else { + assert(false); + return false; + } + } + + // bidi + + constexpr void decrement() { + if constexpr ((Cat & category::category_mask) >= + category::bidirectional) { + --it; + } else { + assert(false); + } + } + + // random access + + constexpr void advance(Diff diff) { + if constexpr ((Cat & category::category_mask) >= + category::random_access) { + it += diff; + } else { + assert(false); + } + } + + constexpr Diff distance_to(const any_iter_interface &other) const { + if constexpr ((Cat & category::category_mask) >= + category::random_access) { + return Diff(it - static_cast(other).it); + } else { + assert(false); + return Diff{}; + } + } + + Iter it; + }; + + struct singular_impl : any_iter_interface { + singular_impl() = default; + + constexpr std::unique_ptr move() { + return std::make_unique(); + } + + constexpr Ref deref() const { assert(false); }; + constexpr void increment() { assert(false); }; + + constexpr RValueRef iter_move() const { assert(false); }; + + using common_interface = std::conditional_t< + std::is_base_of_v, + common_input_iterator, iterator_interface>; + + constexpr virtual std::unique_ptr clone() const { + return std::make_unique(); + } + + constexpr bool equal(const common_interface &other) const { + return dynamic_cast(&other) != nullptr; + } + + // bidi + constexpr void decrement() { assert(false); } + + // random access + + constexpr void advance(Diff) { assert(false); } + constexpr Diff distance_to(const any_iter_interface &) const { + assert(false); + return Diff{}; + } + }; + + struct empty_iterator_category {}; + struct with_iterator_category { + private: + constexpr static auto get_category() { + constexpr auto cat_mask = Cat & category::category_mask; + if constexpr (!std::is_reference_v) { + return std::input_iterator_tag{}; + } else if constexpr (cat_mask >= category::random_access) { + return std::random_access_iterator_tag{}; + } else if constexpr (cat_mask == category::bidirectional) { + return std::bidirectional_iterator_tag{}; + } else if constexpr (cat_mask == category::forward) { + return std::forward_iterator_tag{}; + } else { + return std::input_iterator_tag{}; + } + } + + public: + using iterator_category = decltype(get_category()); + }; + constexpr static auto get_concept() { + constexpr auto cat_mask = Cat & category::category_mask; + if constexpr (cat_mask >= category::random_access) { + return std::random_access_iterator_tag{}; + } else if constexpr (cat_mask == category::bidirectional) { + return std::bidirectional_iterator_tag{}; + } else if constexpr (cat_mask == category::forward) { + return std::forward_iterator_tag{}; + } else { + return std::input_iterator_tag{}; + } + } + struct any_iterator + : std::conditional_t<(Cat & category::category_mask) >= category::forward, + with_iterator_category, empty_iterator_category> { + using iterator_concept = decltype(get_concept()); + using value_type = Value; + using difference_type = Diff; + + constexpr any_iterator() : impl_(std::make_unique()) {} + + template + consteval static bool category_constraint() { + constexpr auto cat_mask = Cat & category::category_mask; + if constexpr (cat_mask == category::contiguous) { + return std::contiguous_iterator; + } else if constexpr (cat_mask == category::random_access) { + return std::random_access_iterator; + } else if constexpr (cat_mask == category::bidirectional) { + return std::bidirectional_iterator; + } else if constexpr (cat_mask == category::forward) { + return std::forward_iterator; + } else { + return std::input_iterator; + } + } + + template + requires(!std::same_as && category_constraint()) + constexpr any_iterator(Iter iter) + : impl_(std::make_unique>(std::move(iter))) {} + + // TODO: do we allow copy for input iterator and how? + constexpr any_iterator(const any_iterator &other) + requires((Cat & category::category_mask) >= category::forward || + (Cat & category::common) != category::none) + { + impl_ = cast_unique_ptr(other.impl_->clone()); + } + + constexpr any_iterator(any_iterator &&other) { + impl_ = cast_unique_ptr(other.impl_->move()); + } + + constexpr any_iterator &operator=(const any_iterator &other) + requires((Cat & category::category_mask) >= category::forward || + (Cat & category::common) != category::none) + { + if (this != &other) { + impl_ = cast_unique_ptr(other.impl_->clone()); + } + return *this; + } + + constexpr any_iterator &operator=(any_iterator &&other) { + if (this != &other) { + impl_ = cast_unique_ptr(other.impl_->move()); + } + return *this; + } + + constexpr Ref operator*() const { return impl_->deref(); } + + constexpr any_iterator &operator++() { + impl_->increment(); + return *this; + } + + constexpr void operator++(int) { ++(*this); } + + constexpr any_iterator operator++(int) + requires((Cat & category::category_mask) >= category::forward) + { + auto tmp = *this; + ++(*this); + return tmp; + } + + constexpr any_iterator &operator--() + requires((Cat & category::category_mask) >= category::bidirectional) + { + impl_->decrement(); + return *this; + } + + constexpr any_iterator operator--(int) + requires((Cat & category::category_mask) >= category::bidirectional) + { + auto tmp = *this; + --(*this); + return tmp; + } + + constexpr any_iterator &operator+=(difference_type n) + requires((Cat & category::category_mask) >= category::random_access) + { + impl_->advance(n); + return *this; + } + + constexpr any_iterator &operator-=(difference_type n) + requires((Cat & category::category_mask) >= category::random_access) + { + *this += -n; + return *this; + } + + constexpr Ref operator[](difference_type n) const + requires((Cat & category::category_mask) >= category::random_access) + { + return *((*this) + n); + } + + friend constexpr bool operator<(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::random_access) + { + return (x - y) < 0; + } + + friend constexpr bool operator>(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::random_access) + { + return (x - y) > 0; + } + + friend constexpr bool operator<=(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::random_access) + { + return (x - y) <= 0; + } + + friend constexpr bool operator>=(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::random_access) + { + return (x - y) >= 0; + } + + friend constexpr any_iterator operator+(const any_iterator &it, + difference_type n) + requires((Cat & category::category_mask) >= category::random_access) + { + auto temp = it; + temp += n; + return temp; + } + + friend constexpr any_iterator operator+(difference_type n, + const any_iterator &it) + requires((Cat & category::category_mask) >= category::random_access) + { + return it + n; + } + + friend constexpr any_iterator operator-(const any_iterator &it, + difference_type n) + requires((Cat & category::category_mask) >= category::random_access) + { + auto temp = it; + temp -= n; + return temp; + } + + friend constexpr difference_type operator-(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::random_access) + { + return x.impl_->distance_to(*(y.impl_)); + } + + friend constexpr bool operator==(const any_iterator &x, + const any_iterator &y) + requires((Cat & category::category_mask) >= category::forward || + (Cat & category::common) != category::none) + { + return x.impl_->equal(*(y.impl_)); + } + + friend constexpr RValueRef iter_move(const any_iterator &iter) { + return iter.impl_->iter_move(); + } + + constexpr any_iter_interface const &get_impl() const { return *impl_; } + + private: + std::unique_ptr impl_; + + constexpr any_iterator(std::unique_ptr &&impl) + : impl_(std::move(impl)) {} + + template + constexpr static std::unique_ptr cast_unique_ptr( + std::unique_ptr &&p) { + return std::unique_ptr( + static_cast(p.release())); + } + }; + + using iterator = std::conditional_t<(Cat & category::category_mask) == + category::contiguous, + std::add_pointer_t, any_iterator>; + struct any_sentinel_interface { + constexpr virtual std::unique_ptr move() = 0; + + constexpr virtual std::unique_ptr clone() const = 0; + + constexpr virtual ~any_sentinel_interface() = default; + + constexpr virtual bool equal(const iterator &) const = 0; + }; + + template + struct sentinel_impl : any_sentinel_interface { + constexpr explicit sentinel_impl(Sent st) : st_(std::move(st)) {} + constexpr std::unique_ptr move() override { + return std::make_unique(std::move(st_)); + } + + constexpr std::unique_ptr clone() const override { + return std::make_unique(st_); + } + + constexpr bool equal(const iterator &iter) const override { + if constexpr ((Cat & category::category_mask) == category::contiguous) { + return st_ == iter; + } else { + if (auto iter_impl = + dynamic_cast const *>(&iter.get_impl())) { + return iter_impl->it == st_; + } + } + return false; + } + + private: + Sent st_; + }; + + struct any_sentinel { + constexpr any_sentinel() = default; + + template + struct tag {}; + + template + constexpr any_sentinel(Sent sent, tag) + : impl_(std::make_unique>(std::move(sent))) {} + + constexpr any_sentinel(const any_sentinel &other) { + if (other.impl_) { + impl_ = other.impl_->clone(); + } + } + + constexpr any_sentinel(any_sentinel &&other) { + if (other.impl_) { + impl_ = other.impl_->move(); + } + } + + constexpr any_sentinel &operator=(const any_sentinel &other) { + if (this != &other) { + impl_ = other.impl_ ? other.impl_->clone() : other.impl_; + } + return *this; + } + + constexpr any_sentinel &operator=(any_sentinel &&other) { + if (this != &other) { + impl_ = other.impl_ ? other.impl_->move() : other.impl_; + } + return *this; + } + + friend constexpr bool operator==(const iterator &iter, + const any_sentinel &sent) { + if (!sent.impl_) return false; + return sent.impl_->equal(iter); + } + + private: + std::unique_ptr impl_ = nullptr; + + constexpr any_sentinel(std::unique_ptr &&impl) + : impl_(std::move(impl)) {} + }; + + using sentinel = + std::conditional_t<(Cat & category::common) == category::none, + any_sentinel, iterator>; + + struct sized_interface { + constexpr virtual std::size_t size() const = 0; + }; + + template + struct clonable_interface { + constexpr virtual std::unique_ptr clone() const = 0; + }; + + template + struct basic_any_view_interface { + constexpr virtual std::unique_ptr move() = 0; + + constexpr virtual iterator begin() = 0; + constexpr virtual sentinel end() = 0; + + constexpr virtual ~basic_any_view_interface() = default; + }; + + struct any_view_interface : basic_any_view_interface, + sized_interface, + clonable_interface {}; + + template + struct any_view_impl : any_view_interface { + constexpr explicit any_view_impl(View view) : view_(std::move(view)) {} + + constexpr std::unique_ptr move() override { + return std::make_unique(std::move(view_)); + } + + constexpr std::unique_ptr clone() const override { + if constexpr ((Cat & category::move_only_view) == category::none) { + return std::make_unique(view_); + } else { + assert(false); + return nullptr; + } + } + + constexpr iterator begin() override { + if constexpr ((Cat & category::category_mask) == category::contiguous) { + return std::ranges::begin(view_); + } else { + return any_iterator(std::ranges::begin(view_)); + } + } + + constexpr sentinel end() override { + if constexpr ((Cat & category::category_mask) == category::contiguous && + (Cat & category::common) != category::none) { + return std::ranges::end(view_); + } else if constexpr ((Cat & category::common) != category::none) { + return any_iterator(std::ranges::end(view_)); + } else { + using tag_t = any_sentinel::template tag>; + return any_sentinel(std::ranges::end(view_), tag_t{}); + } + } + + constexpr std::size_t size() const override { + if constexpr ((Cat & category::sized) != category::none) { + return std::ranges::size(view_); + } else { + assert(false); + return 0; + } + } + + private: + View view_; + }; + + template + consteval static bool view_category_constraint() { + if constexpr ((Cat & category::sized) != category::none && + !std::ranges::sized_range) { + return false; + } + + if constexpr ((Cat & category::common) != category::none && + !std::ranges::common_range) { + return false; + } + + if constexpr ((Cat & category::borrowed) != category::none && + !std::ranges::borrowed_range) { + return false; + } + + if constexpr ((Cat & category::move_only_view) == category::none && + !std::copyable) { + return false; + } + constexpr auto cat_mask = Cat & category::category_mask; + if constexpr (cat_mask == category::contiguous) { + return std::ranges::contiguous_range; + } else if constexpr (cat_mask == category::random_access) { + return std::ranges::random_access_range; + } else if constexpr (cat_mask == category::bidirectional) { + return std::ranges::bidirectional_range; + } else if constexpr (cat_mask == category::forward) { + return std::ranges::forward_range; + } else { + return std::ranges::input_range; + } + } + + template + requires(!std::same_as && std::ranges::view && + view_category_constraint()) + constexpr any_view(View view) + : impl_(std::make_unique>(std::move(view))) {} + + constexpr any_view(const any_view &other) + requires((Cat & category::move_only_view) == category::none) + : impl_(other.impl_->clone()) {} + + constexpr any_view(any_view &&other) : impl_(other.impl_->move()) {} + + constexpr any_view &operator=(const any_view &other) + requires((Cat & category::move_only_view) == category::none) + { + if (this != &other) { + impl_ = other.impl_->clone(); + } + return *this; + } + + constexpr any_view &operator=(any_view &&other) { + if (this != &other) { + impl_ = other.impl_->move(); + } + return *this; + } + + constexpr iterator begin() { return impl_->begin(); } + constexpr sentinel end() { return impl_->end(); } + + constexpr std::size_t size() const + requires((Cat & category::sized) != category::none) + { + return impl_->size(); + } + + private: + std::unique_ptr impl_; +}; + +template +inline constexpr bool + enable_borrowed_range> = + (Cat & category::borrowed) != category::none; + +} // namespace std::ranges + +#endif