Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions include/beman/any_view/any_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,6 @@
#include <beman/any_view/detail/polymorphic_view.hpp>

namespace beman::any_view {
namespace detail {

template <class T>
struct rvalue_ref {
using type = T;
};

template <class T>
struct rvalue_ref<T&> {
using type = T&&;
};

template <class T>
using rvalue_ref_t = typename rvalue_ref<T>::type;

} // namespace detail

template <class ElementT,
any_view_options OptsV = any_view_options::input,
Expand Down
4 changes: 2 additions & 2 deletions include/beman/any_view/detail/iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ class iterator : public iterator_category_type<iterator_concept_t<OptsV>, std::i
static constexpr bool random_access = flag_is_set<OptsV, any_view_options::random_access>;
static constexpr bool contiguous = flag_is_set<OptsV, any_view_options::contiguous>;

// do not cache an iterator reference without multi-pass guarantee
using cache_type = std::conditional_t<forward, iter_cache_t<RefT>, no_cache>;
using cache_type =
std::conditional_t<convertible_to_borrowed<rvalue_ref_t<RefT>, RValueRefT>, iter_cache_t<RefT>, no_cache>;
using polymorphic_type = polymorphic_iterator<RefT, RValueRefT, DiffT, OptsV>;

static constexpr bool has_cache = not std::is_same_v<cache_type, no_cache>;
Expand Down
43 changes: 26 additions & 17 deletions include/beman/any_view/detail/polymorphic_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,29 +227,38 @@ struct subtract_t : symmetric_binary_protocol {
// inplace storage sufficient for two pointers
using iterator_storage = small_storage<2 * sizeof(void*)>;

template <class RefT, class RValueRefT>
struct input_protocol : inherit<move_t<iterator_storage>,
destroy_t<iterator_storage>,
dereference_t<RefT>,
iter_move_t<RValueRefT>,
increment_t,
sentinel_compare_t> {};

template <class RefT>
concept has_cache = not std::same_as<iter_cache_t<RefT>, no_cache>;

template <class RefT>
struct forward_cache_protocol : inherit<> {};
template <class T>
struct rvalue_ref {
using type = T;
};

template <has_cache RefT>
struct forward_cache_protocol<RefT> : inherit<cache_t<RefT>, next_t<RefT>> {};
template <class T>
struct rvalue_ref<T&> {
using type = 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>> {};

template <class RefT, class RValueRefT>
struct input_protocol : inherit<move_t<iterator_storage>,
destroy_t<iterator_storage>,
input_cache_protocol<RefT, RValueRefT>,
sentinel_compare_t> {};

template <class RefT, class RValueRefT>
struct forward_protocol : inherit<input_protocol<RefT, RValueRefT>,
copy_t<iterator_storage>,
forward_cache_protocol<RefT>,
type_t,
equality_compare_t> {};
struct forward_protocol
: inherit<input_protocol<RefT, RValueRefT>, copy_t<iterator_storage>, type_t, equality_compare_t> {};

template <class RefT>
struct bidirectional_cache_protocol : inherit<decrement_t> {};
Expand Down
16 changes: 13 additions & 3 deletions tests/beman/any_view/constexpr.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,20 @@ TEST(ConstexprTest, sort_vector) {
EXPECT_TRUE(sort(std::vector{6, 8, 7, 5, 3, 0, 9}));
}

template <class T>
struct non_trivially_copyable {
T value;

non_trivially_copyable(const non_trivially_copyable&);
};

template <class T>
non_trivially_copyable<T>::non_trivially_copyable(const non_trivially_copyable&) = default;

constexpr auto set_front(any_view<int, forward> view, int value) {
// forward iterator of lvalue reference uses cache object to fuse virtual dispatches
static_assert(sizeof(std::ranges::iterator_t<any_view<int, forward>>) ==
sizeof(std::ranges::iterator_t<any_view<int, input>>) + sizeof(int*));
// lvalue reference uses cache object to fuse virtual dispatches
static_assert(sizeof(std::ranges::iterator_t<any_view<int>>) ==
sizeof(std::ranges::iterator_t<proxy_any_view<non_trivially_copyable<int>>>) + sizeof(int*));

auto& ref = view.front();
// even with cache object, lifetime of reference is not tied to lifetime of iterator
Expand Down
Loading