From d0fb9fdc239f9069b184e783d522286b5169ab79 Mon Sep 17 00:00:00 2001 From: Hui Date: Fri, 31 May 2024 13:17:57 +0100 Subject: [PATCH] type erasure global vtable --- impl/any_view/any_view_te.hpp | 425 +++++++++++++++++----------------- 1 file changed, 214 insertions(+), 211 deletions(-) diff --git a/impl/any_view/any_view_te.hpp b/impl/any_view/any_view_te.hpp index 5c386ae..790040d 100644 --- a/impl/any_view/any_view_te.hpp +++ b/impl/any_view/any_view_te.hpp @@ -114,6 +114,101 @@ class any_view { using any_iterator_vtable = iterator_vtable; + 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))); + } + }; + struct empty_iterator_category {}; struct with_iterator_category { private: @@ -159,15 +254,16 @@ class any_view { constexpr any_iterator(const any_iterator &other) requires((Cat & category::category_mask) >= category::forward || (Cat & category::common) != category::none) - : parent_(other.parent_) { + : iter_vtable_(other.iter_vtable_) { if (!other.is_singular()) { - iter_ = (*(other.parent_->iter_vtable_.copy_))(other.iter_); + iter_ = (*(other.iter_vtable_->copy_))(other.iter_); } } - constexpr any_iterator(any_iterator &&other) : parent_(other.parent_) { + constexpr any_iterator(any_iterator &&other) + : iter_vtable_(other.iter_vtable_) { if (!other.is_singular()) { - iter_ = (*(other.parent_->iter_vtable_.move_))(other.iter_); + iter_ = (*(other.iter_vtable_->move_))(other.iter_); } } @@ -177,12 +273,12 @@ class any_view { { if (this != &other) { if (!is_singular()) { - (*(parent_->iter_vtable_.destructor_))(iter_); + (*(iter_vtable_->destructor_))(iter_); } if (!other.is_singular()) { - iter_ = (*(other.parent_->iter_vtable_.copy_))(other.iter_); + iter_ = (*(other.iter_vtable_->copy_))(other.iter_); } - parent_ = other.parent_; + iter_vtable_ = other.iter_vtable_; } return *this; } @@ -190,30 +286,30 @@ class any_view { constexpr any_iterator &operator=(any_iterator &&other) { if (this != &other) { if (!is_singular()) { - (*(parent_->iter_vtable_.destructor_))(iter_); + (*(iter_vtable_->destructor_))(iter_); } if (!other.is_singular()) { - iter_ = (*(other.parent_->iter_vtable_.move_))(other.iter_); + iter_ = (*(other.iter_vtable_->move_))(other.iter_); } - parent_ = other.parent_; + iter_vtable_ = other.iter_vtable_; } return *this; } constexpr ~any_iterator() { if (!is_singular()) { - (*(parent_->iter_vtable_.destructor_))(iter_); + (*(iter_vtable_->destructor_))(iter_); } } constexpr Ref operator*() const { - assert(parent_); - return (*(parent_->iter_vtable_.deref_))(iter_); + assert(iter_vtable_); + return (*(iter_vtable_->deref_))(iter_); } constexpr any_iterator &operator++() { - assert(parent_); - (*(parent_->iter_vtable_.increment_))(iter_); + assert(iter_vtable_); + (*(iter_vtable_->increment_))(iter_); return *this; } @@ -230,8 +326,8 @@ class any_view { constexpr any_iterator &operator--() requires((Cat & category::category_mask) >= category::bidirectional) { - assert(parent_); - (*(parent_->iter_vtable_.decrement_))(iter_); + assert(iter_vtable_); + (*(iter_vtable_->decrement_))(iter_); return *this; } @@ -246,8 +342,8 @@ class any_view { constexpr any_iterator &operator+=(difference_type n) requires((Cat & category::category_mask) >= category::random_access) { - assert(parent_); - (*(parent_->iter_vtable_.advance_))(iter_, n); + assert(iter_vtable_); + (*(iter_vtable_->advance_))(iter_, n); return *this; } @@ -321,10 +417,10 @@ class any_view { 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_); + assert(x.iter_vtable_); + assert(y.iter_vtable_); + assert(x.iter_vtable_ == y.iter_vtable_); + return (*(x.iter_vtable_->distance_to_))(x.iter_, y.iter_); } friend constexpr bool operator==(const any_iterator &x, @@ -332,157 +428,93 @@ class any_view { 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_); + if (x.iter_vtable_ != y.iter_vtable_) return false; + if (!x.iter_vtable_) return true; + return (*(x.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_); + assert(iter.iter_vtable_); + return (*(iter.iter_vtable_->iter_move_))(iter.iter_); } // private: - any_view *parent_ = nullptr; + const any_iterator_vtable *iter_vtable_ = nullptr; void *iter_ = nullptr; template - constexpr any_iterator(any_view *parent, Iter iter) - : parent_(parent), iter_(new Iter(std::move(iter))) {} + constexpr any_iterator(const any_iterator_vtable *table, Iter iter) + : iter_vtable_(table), iter_(new Iter(std::move(iter))) {} - constexpr bool is_singular() const { return !parent_; } + constexpr bool is_singular() const { return !iter_vtable_; } }; - 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))); - } + using iterator = std::conditional_t<(Cat & category::category_mask) == + category::contiguous, + std::add_pointer_t, any_iterator>; - template - static constexpr void destroy(void *self) { - return std::destroy_at(static_cast(self)); - } + struct sentinel_vtable : movable_vtable, copyable_vtable, destructor_vtable { + bool (*equal_)(const iterator &, const any_sentinel &); }; - 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; - } + struct any_sentinel_vtable + : maybe_t {}; - if constexpr ((Cat & category::category_mask) >= - category::bidirectional) { - t.decrement_ = &decrement; - } + struct sentinel_vtable_gen : basic_vtable_gen { + template + static constexpr auto generate() { + any_sentinel_vtable t; - if constexpr ((Cat & category::category_mask) >= - category::random_access) { - t.advance_ = &advance; - t.distance_to_ = &distance_to; - } + 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; - } - // 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; + return t; } - template - static constexpr Diff distance_to(const void *self, const void *other) { - return Diff((*static_cast(self)) - - (*static_cast(other))); + 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_); + } } }; - 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_) { + constexpr any_sentinel(const any_sentinel &other) + : sent_vtable_(other.sent_vtable_) { if (!other.is_singular()) { - sent_ = (*(other.parent_->sent_vtable_.copy_))(other.sent_); + sent_ = (*(other.sent_vtable_->copy_))(other.sent_); } } - constexpr any_sentinel(any_sentinel &&other) : parent_(other.parent_) { + constexpr any_sentinel(any_sentinel &&other) + : sent_vtable_(other.sent_vtable_) { if (!other.is_singular()) { - sent_ = (*(other.parent_->sent_vtable_.move_))(other.sent_); + sent_ = (*(other.sent_vtable_->move_))(other.sent_); } } constexpr any_sentinel &operator=(const any_sentinel &other) { if (this != &other) { if (!is_singular()) { - (*(parent_->sent_vtable_.destructor_))(sent_); + (*(sent_vtable_->destructor_))(sent_); } if (!other.is_singular()) { - sent_ = (*(other.parent_->sent_vtable_.copy_))(other.sent_); + sent_ = (*(other.sent_vtable_->copy_))(other.sent_); } - parent_ = other.parent_; + sent_vtable_ = other.sent_vtable_; } return *this; } @@ -490,89 +522,60 @@ class any_view { constexpr any_sentinel &operator=(any_sentinel &&other) { if (this != &other) { if (!is_singular()) { - (*(parent_->sent_vtable_.destructor_))(sent_); + (*(sent_vtable_->destructor_))(sent_); } if (!other.is_singular()) { - sent_ = (*(other.parent_->sent_vtable_.move_))(other.sent_); + sent_ = (*(other.sent_vtable_->move_))(other.sent_); } - parent_ = other.parent_; + sent_vtable_ = other.sent_vtable_; } return *this; } constexpr ~any_sentinel() { if (!is_singular()) { - (*(parent_->sent_vtable_.destructor_))(sent_); + (*(sent_vtable_->destructor_))(sent_); } } friend constexpr bool operator==(const iterator &iter, const any_sentinel &sent) { - return (*(sent.parent_->sent_vtable_.equal_))(iter, sent); + return (*(sent.sent_vtable_->equal_))(iter, sent); } // private: - any_view *parent_ = nullptr; + const any_sentinel_vtable *sent_vtable_ = nullptr; void *sent_ = nullptr; template - constexpr any_sentinel(any_view *parent, Sent sent) - : parent_(parent), sent_(new Sent(std::move(sent))) {} + constexpr any_sentinel(const any_sentinel_vtable *table, Sent sent) + : sent_vtable_(table), sent_(new Sent(std::move(sent))) {} - constexpr bool is_singular() const { return !parent_; } + constexpr bool is_singular() const { return !sent_vtable_; } }; 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 + struct any_view_vtable : destructor_vtable, movable_vtable, maybe_t, maybe_t { - iterator (*begin_)(any_view *); - sentinel (*end_)(any_view *); + iterator (*begin_)(void *); + sentinel (*end_)(void *); }; struct view_vtable_gen : basic_vtable_gen { template static constexpr auto generate() { - view_vtable t; + any_view_vtable t; t.move_ = &basic_vtable_gen::template move; t.destructor_ = &basic_vtable_gen::template destroy; @@ -591,25 +594,29 @@ class any_view { } template - static constexpr iterator begin(any_view *av) { - auto &view = *(static_cast(av->view_)); + static constexpr iterator begin(void *v) { + auto &view = *(static_cast(v)); if constexpr ((Cat & category::category_mask) == category::contiguous) { return std::ranges::begin(view); } else { - return any_iterator(av, std::ranges::begin(view)); + return any_iterator(&iter_vtable>, + std::ranges::begin(view)); } } template - static constexpr sentinel end(any_view *av) { - auto &view = *(static_cast(av->view_)); + static constexpr sentinel end(void *v) { + auto &view = *(static_cast(v)); 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)); + return any_iterator(&iter_vtable>, + std::ranges::end(view)); } else { - return any_sentinel(av, std::ranges::end(view)); + return any_sentinel(&sent_vtable, + std::ranges::sentinel_t>, + std::ranges::end(view)); } } @@ -658,35 +665,23 @@ class any_view { 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))) {} + : view_vtable_(&view_vtable), 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_)) {} + : 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_)) {} + : 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_->destructor_))(view_); + view_ = (*(other.view_vtable_->copy_))(other.view_); view_vtable_ = other.view_vtable_; } return *this; @@ -694,28 +689,36 @@ class any_view { 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_->destructor_))(view_); + view_ = (*(other.view_vtable_->move_))(other.view_); view_vtable_ = other.view_vtable_; } return *this; } - constexpr iterator begin() { return (*(view_vtable_.begin_))(this); } - constexpr sentinel end() { return (*(view_vtable_.end_))(this); } + constexpr iterator begin() { return (*(view_vtable_->begin_))(view_); } + constexpr sentinel end() { return (*(view_vtable_->end_))(view_); } constexpr std::size_t size() const requires((Cat & category::sized) != category::none) { - return (*(view_vtable_.size_))(view_); + return (*(view_vtable_->size_))(view_); } private: - any_iterator_vtable iter_vtable_; - any_sentinel_vtable sent_vtable_; - view_vtable view_vtable_; + template + static constexpr any_iterator_vtable iter_vtable = + iterator_vtable_gen::template generate(); + + template + static constexpr any_sentinel_vtable sent_vtable = + sentinel_vtable_gen::template generate(); + + template + static constexpr any_view_vtable view_vtable = + view_vtable_gen::template generate(); + + const any_view_vtable *view_vtable_; void *view_; };