-
Notifications
You must be signed in to change notification settings - Fork 9
Fix #85 and #86 #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #85 and #86 #87
Changes from all commits
d8a1b23
af6d033
dbc549a
4d86cb0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,46 +51,37 @@ class basic_polymorphic { | |
| constexpr ~basic_polymorphic() { entry(destroy_t<StorageT>{})(storage); } | ||
|
|
||
| constexpr basic_polymorphic& operator=(const basic_polymorphic& other) { | ||
| if (this == std::addressof(other)) { | ||
| return *this; | ||
| if (this != std::addressof(other)) { | ||
| *this = basic_polymorphic(other); | ||
| } | ||
|
|
||
| std::destroy_at(this); | ||
| std::construct_at(this, other); | ||
| return *this; | ||
| } | ||
|
|
||
| constexpr basic_polymorphic& operator=(basic_polymorphic&& other) noexcept { | ||
| if (this == std::addressof(other)) { | ||
| return *this; | ||
| if (this != std::addressof(other)) { | ||
| std::destroy_at(this); | ||
| std::construct_at(this, std::move(other)); | ||
| } | ||
|
|
||
| std::destroy_at(this); | ||
| std::construct_at(this, std::move(other)); | ||
| return *this; | ||
| } | ||
|
|
||
| template <adaptor AdaptorT> | ||
| constexpr basic_polymorphic& operator=(AdaptorT&& adaptor) { | ||
| std::destroy_at(this); | ||
| std::construct_at(this, std::forward<AdaptorT>(adaptor)); | ||
| return *this; | ||
| return *this = basic_polymorphic(std::forward<AdaptorT>(adaptor)); | ||
| } | ||
|
|
||
| // converting assignment | ||
|
|
||
| template <std::derived_from<ProtocolTs>... OtherProtocolTs> | ||
| constexpr basic_polymorphic& operator=(const basic_polymorphic<StorageT, OtherProtocolTs...>& other) { | ||
| std::destroy_at(this); | ||
| std::construct_at(this, other); | ||
| return *this; | ||
| return *this = basic_polymorphic(other); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For this and converting move assignment, would prefer to use explicit template parameters on |
||
| } | ||
|
|
||
| template <std::derived_from<ProtocolTs>... OtherProtocolTs> | ||
| constexpr basic_polymorphic& operator=(basic_polymorphic<StorageT, OtherProtocolTs...>&& other) noexcept { | ||
| std::destroy_at(this); | ||
| std::construct_at(this, std::move(other)); | ||
| return *this; | ||
| return *this = basic_polymorphic(std::move(other)); | ||
| } | ||
|
|
||
| constexpr StorageT& get() & noexcept { return storage; } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,6 +48,17 @@ struct sentinel_compare_t : unary_protocol { | |
| } | ||
| }; | ||
|
|
||
| template <class DiffT> | ||
| struct sentinel_compare_at_t : unary_protocol { | ||
| template <not_adaptor T> | ||
| static bool fn(const T& self, DiffT offset); | ||
|
|
||
| template <adaptor IteratorAdaptorT> | ||
| [[nodiscard]] static constexpr bool fn(const IteratorAdaptorT& adaptor, DiffT offset) { | ||
| return adaptor.iterator + offset == adaptor.sentinel; | ||
| } | ||
| }; | ||
|
|
||
| template <class RefT> | ||
| struct dereference_t : unary_protocol { | ||
| template <not_adaptor T> | ||
|
|
@@ -243,22 +254,27 @@ struct rvalue_ref<T&> { | |
| template <class T> | ||
| using rvalue_ref_t = typename rvalue_ref<T>::type; | ||
|
|
||
| template <class RefT, class RValueRefT> | ||
| struct input_cache_protocol : inherit<dereference_t<RefT>, iter_move_t<RValueRefT>, increment_t> {}; | ||
|
|
||
| template <has_cache RefT, class RValueRefT> | ||
| requires convertible_to_borrowed<rvalue_ref_t<RefT>, RValueRefT> | ||
| struct input_cache_protocol<RefT, RValueRefT> : inherit<cache_t<RefT>, next_t<RefT>> {}; | ||
|
Comment on lines
-246
to
-251
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This and related changes to restrict where caching is applied need to be reverted. |
||
|
|
||
| template <class RefT, class RValueRefT> | ||
| struct input_protocol : inherit<move_t<iterator_storage>, | ||
| destroy_t<iterator_storage>, | ||
| input_cache_protocol<RefT, RValueRefT>, | ||
| dereference_t<RefT>, | ||
| iter_move_t<RValueRefT>, | ||
| increment_t, | ||
| sentinel_compare_t> {}; | ||
|
|
||
| template <class RefT, class RValueRefT> | ||
| struct forward_protocol | ||
| : inherit<input_protocol<RefT, RValueRefT>, copy_t<iterator_storage>, type_t, equality_compare_t> {}; | ||
| struct forward_cache_protocol : inherit<> {}; | ||
|
|
||
| template <has_cache RefT, class RValueRefT> | ||
| requires convertible_to_borrowed<rvalue_ref_t<RefT>, RValueRefT> | ||
| struct forward_cache_protocol<RefT, RValueRefT> : inherit<cache_t<RefT>, next_t<RefT>> {}; | ||
|
|
||
| template <class RefT, class RValueRefT> | ||
| struct forward_protocol : inherit<input_protocol<RefT, RValueRefT>, | ||
| copy_t<iterator_storage>, | ||
| forward_cache_protocol<RefT, RValueRefT>, | ||
| type_t, | ||
| equality_compare_t> {}; | ||
|
|
||
| template <class RefT> | ||
| struct bidirectional_cache_protocol : inherit<decrement_t> {}; | ||
|
|
@@ -278,6 +294,7 @@ struct random_access_cache_protocol<RefT, RValueRefT, DiffT> : inherit<advance_t | |
| template <class RefT, class RValueRefT, class DiffT> | ||
| struct random_access_protocol : inherit<bidirectional_protocol<RefT, RValueRefT>, | ||
| random_access_cache_protocol<RefT, RValueRefT, DiffT>, | ||
| sentinel_compare_at_t<DiffT>, | ||
| three_way_compare_t, | ||
| subtract_t<DiffT>> {}; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <cstddef> | ||
| #include <iterator> | ||
| #include <ranges> | ||
| #include <type_traits> | ||
| #include <utility> | ||
|
|
||
| struct self_ref_forward_proxy { | ||
| const int* pointer{}; | ||
|
|
||
| operator int() const noexcept { return *pointer; } | ||
| }; | ||
|
|
||
| static_assert(std::is_trivially_copyable_v<self_ref_forward_proxy>); | ||
|
|
||
| struct self_ref_forward_proxy_iterator { | ||
| using value_type = int; | ||
| using difference_type = std::ptrdiff_t; | ||
| using iterator_concept = std::forward_iterator_tag; | ||
|
|
||
| mutable int value{}; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you clarify why |
||
| int stop{}; | ||
|
|
||
| self_ref_forward_proxy_iterator() = default; | ||
|
|
||
| self_ref_forward_proxy_iterator(int value, int stop) : value(value), stop(stop) {} | ||
|
|
||
| self_ref_forward_proxy_iterator(const self_ref_forward_proxy_iterator&) = default; | ||
|
|
||
| self_ref_forward_proxy_iterator& operator=(const self_ref_forward_proxy_iterator&) = default; | ||
|
|
||
| self_ref_forward_proxy_iterator(self_ref_forward_proxy_iterator&& other) noexcept | ||
| : value(other.value), stop(other.stop) { | ||
| other.value = -777; | ||
| } | ||
|
|
||
| self_ref_forward_proxy_iterator& operator=(self_ref_forward_proxy_iterator&& other) noexcept { | ||
| value = other.value; | ||
| stop = other.stop; | ||
|
|
||
| other.value = -777; | ||
| return *this; | ||
| } | ||
|
|
||
| self_ref_forward_proxy operator*() const noexcept { | ||
| // The proxy points into this iterator. | ||
| return {&value}; | ||
| } | ||
|
|
||
| self_ref_forward_proxy_iterator& operator++() noexcept { | ||
| ++value; | ||
| return *this; | ||
| } | ||
|
|
||
| self_ref_forward_proxy_iterator operator++(int) noexcept { | ||
| auto previous = *this; | ||
| ++*this; | ||
| return previous; | ||
| } | ||
|
|
||
| friend bool operator==(const self_ref_forward_proxy_iterator&, const self_ref_forward_proxy_iterator&) = default; | ||
| }; | ||
|
|
||
| static_assert(std::forward_iterator<self_ref_forward_proxy_iterator>); | ||
|
|
||
| struct self_ref_forward_proxy_view : std::ranges::view_base { | ||
| int first{}; | ||
| int stop{}; | ||
|
|
||
| self_ref_forward_proxy_view() = default; | ||
|
|
||
| self_ref_forward_proxy_view(int first, int stop) : first(first), stop(stop) {} | ||
|
|
||
| self_ref_forward_proxy_iterator begin() const noexcept { return {first, stop}; } | ||
|
|
||
| self_ref_forward_proxy_iterator end() const noexcept { return {stop, stop}; } | ||
| }; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be |
||
|
|
||
| static_assert(std::ranges::forward_range<self_ref_forward_proxy_view>); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <beman/any_view/any_view.hpp> | ||
|
|
||
| struct self_ref_input_iterator { | ||
| using value_type = int; | ||
| using difference_type = std::ptrdiff_t; | ||
| using iterator_concept = std::input_iterator_tag; | ||
|
|
||
| mutable int value{}; | ||
| int stop{}; | ||
|
|
||
| self_ref_input_iterator() = delete; | ||
|
|
||
| self_ref_input_iterator(int value, int stop) : value(value), stop(stop) {} | ||
|
|
||
| self_ref_input_iterator(const self_ref_input_iterator&) = delete; | ||
| self_ref_input_iterator& operator=(const self_ref_input_iterator&) = delete; | ||
|
|
||
| self_ref_input_iterator(self_ref_input_iterator&& other) noexcept : value(other.value), stop(other.stop) { | ||
| other.value = -777; | ||
| } | ||
|
|
||
| self_ref_input_iterator& operator=(self_ref_input_iterator&& other) noexcept { | ||
| value = other.value; | ||
| stop = other.stop; | ||
|
|
||
| other.value = -777; | ||
| return *this; | ||
| } | ||
|
|
||
| int& operator*() const noexcept { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sure you could make your point with |
||
| // The returned reference points inside this iterator. | ||
| return value; | ||
| } | ||
|
|
||
| self_ref_input_iterator& operator++() noexcept { | ||
| ++value; | ||
| return *this; | ||
| } | ||
|
|
||
| void operator++(int) noexcept { ++*this; } | ||
|
|
||
| friend bool operator==(const self_ref_input_iterator& iterator, std::default_sentinel_t) noexcept { | ||
| return iterator.value == iterator.stop; | ||
| } | ||
| }; | ||
|
|
||
| static_assert(std::input_iterator<self_ref_input_iterator>); | ||
|
|
||
| struct self_ref_input_view : std::ranges::view_base { | ||
| int first{}; | ||
| int stop{}; | ||
|
|
||
| self_ref_input_view() = default; | ||
|
|
||
| self_ref_input_view(int first, int stop) : first(first), stop(stop) {} | ||
|
|
||
| self_ref_input_iterator begin() { return {first, stop}; } | ||
|
|
||
| std::default_sentinel_t end() const noexcept { return {}; } | ||
| }; | ||
|
Comment on lines
+53
to
+64
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be |
||
|
|
||
| static_assert(std::ranges::input_range<self_ref_input_view>); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <cstddef> | ||
| #include <iterator> | ||
| #include <ranges> | ||
| #include <utility> | ||
|
|
||
| struct throwing_copy_error {}; | ||
|
|
||
| struct throwing_forward_iterator { | ||
| using value_type = int; | ||
| using difference_type = std::ptrdiff_t; | ||
| using iterator_concept = std::forward_iterator_tag; | ||
|
|
||
| inline static bool throw_on_copy = false; | ||
| inline static int live_count = 0; | ||
|
|
||
| int* current{}; | ||
|
|
||
| throwing_forward_iterator() noexcept { ++live_count; } | ||
|
|
||
| explicit throwing_forward_iterator(int* current) noexcept : current(current) { ++live_count; } | ||
|
|
||
| throwing_forward_iterator(const throwing_forward_iterator& other) : current(other.current) { | ||
| if (throw_on_copy) { | ||
| throw throwing_copy_error{}; | ||
| } | ||
|
|
||
| ++live_count; | ||
| } | ||
|
|
||
| throwing_forward_iterator(throwing_forward_iterator&& other) noexcept | ||
| : current(std::exchange(other.current, nullptr)) { | ||
| ++live_count; | ||
| } | ||
|
|
||
| throwing_forward_iterator& operator=(const throwing_forward_iterator& other) { | ||
| if (throw_on_copy) { | ||
| throw throwing_copy_error{}; | ||
| } | ||
|
|
||
| current = other.current; | ||
| return *this; | ||
| } | ||
|
|
||
| throwing_forward_iterator& operator=(throwing_forward_iterator&& other) noexcept { | ||
| current = std::exchange(other.current, nullptr); | ||
| return *this; | ||
| } | ||
|
|
||
| ~throwing_forward_iterator() { --live_count; } | ||
|
|
||
| int& operator*() const noexcept { return *current; } | ||
|
|
||
| throwing_forward_iterator& operator++() noexcept { | ||
| ++current; | ||
| return *this; | ||
| } | ||
|
|
||
| throwing_forward_iterator operator++(int) { | ||
| auto previous = *this; | ||
| ++*this; | ||
| return previous; | ||
| } | ||
|
|
||
| friend bool operator==(const throwing_forward_iterator&, const throwing_forward_iterator&) = default; | ||
| }; | ||
|
|
||
| static_assert(std::forward_iterator<throwing_forward_iterator>); | ||
|
|
||
| struct throwing_forward_view : std::ranges::view_base { | ||
| int* first{}; | ||
| int* last{}; | ||
|
|
||
| throwing_forward_view() = default; | ||
|
|
||
| throwing_forward_view(int* first, int* last) : first(first), last(last) {} | ||
|
|
||
| throwing_forward_iterator begin() const noexcept { return throwing_forward_iterator{first}; } | ||
|
|
||
| throwing_forward_iterator end() const noexcept { return throwing_forward_iterator{last}; } | ||
| }; | ||
|
Comment on lines
+73
to
+84
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can just be |
||
|
|
||
| static_assert(std::ranges::forward_range<throwing_forward_view>); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change adds nothing