| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_LAZY_SPLIT_TYPES_H |
| #define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_LAZY_SPLIT_TYPES_H |
| |
| #include <concepts> |
| #include <cstddef> |
| #include <ranges> |
| #include <string> |
| #include <string_view> |
| #include <type_traits> |
| #include "test_macros.h" |
| #include "test_iterators.h" |
| |
| // CopyableView |
| |
| struct CopyableView : std::ranges::view_base { |
| std::string_view view_; |
| constexpr explicit CopyableView() = default; |
| constexpr CopyableView(const char* ptr) : view_(ptr) {} |
| constexpr CopyableView(std::string_view v) : view_(v) {} |
| constexpr forward_iterator<std::string_view::const_iterator> begin() const { return forward_iterator<std::string_view::const_iterator>(view_.begin()); } |
| constexpr forward_iterator<std::string_view::const_iterator> end() const { return forward_iterator<std::string_view::const_iterator>(view_.end()); } |
| constexpr bool operator==(const CopyableView& rhs) const { return view_ == rhs.view_; } |
| }; |
| static_assert( std::ranges::forward_range<CopyableView>); |
| static_assert( std::ranges::forward_range<const CopyableView>); |
| static_assert( std::ranges::view<CopyableView>); |
| static_assert( std::is_copy_constructible_v<CopyableView>); |
| |
| // ForwardView |
| |
| struct ForwardView : std::ranges::view_base { |
| std::string_view view_; |
| constexpr explicit ForwardView() = default; |
| constexpr ForwardView(const char* ptr) : view_(ptr) {} |
| constexpr ForwardView(std::string_view v) : view_(v) {} |
| constexpr ForwardView(ForwardView&&) = default; |
| constexpr ForwardView& operator=(ForwardView&&) = default; |
| constexpr forward_iterator<std::string_view::const_iterator> begin() const { return forward_iterator<std::string_view::const_iterator>(view_.begin()); } |
| constexpr forward_iterator<std::string_view::const_iterator> end() const { return forward_iterator<std::string_view::const_iterator>(view_.end()); } |
| }; |
| static_assert( std::ranges::forward_range<ForwardView>); |
| static_assert( std::ranges::forward_range<const ForwardView>); |
| static_assert( std::ranges::view<ForwardView>); |
| static_assert(!std::is_copy_constructible_v<ForwardView>); |
| static_assert( std::is_move_constructible_v<ForwardView>); |
| |
| // ForwardDiffView |
| |
| // Iterator types differ based on constness of this class. |
| struct ForwardDiffView : std::ranges::view_base { |
| std::string buffer_; |
| constexpr explicit ForwardDiffView() = default; |
| constexpr ForwardDiffView(const char* ptr) : ForwardDiffView(std::string_view(ptr)) {} |
| constexpr ForwardDiffView(std::string_view v) { |
| // Workaround https://github.com/llvm/llvm-project/issues/55867 |
| buffer_ = v; |
| } |
| constexpr ForwardDiffView(ForwardDiffView&&) = default; |
| constexpr ForwardDiffView& operator=(ForwardDiffView&&) = default; |
| constexpr ForwardDiffView(const ForwardDiffView&) = default; |
| constexpr ForwardDiffView& operator=(const ForwardDiffView&) = default; |
| constexpr forward_iterator<char*> begin() { return forward_iterator<char*>(buffer_.begin().base()); } |
| constexpr forward_iterator<char*> end() { return forward_iterator<char*>(buffer_.end().base()); } |
| constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(buffer_.begin().base()); } |
| constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(buffer_.end().base()); } |
| }; |
| static_assert( std::ranges::forward_range<ForwardView>); |
| static_assert( std::ranges::forward_range<const ForwardView>); |
| static_assert( std::ranges::view<ForwardView>); |
| static_assert(!std::same_as<std::ranges::iterator_t<ForwardDiffView>, std::ranges::iterator_t<const ForwardDiffView>>); |
| |
| // ForwardOnlyIfNonConstView |
| |
| template <class It> |
| class almost_forward_iterator { |
| It it_; |
| |
| template <class U> friend class almost_forward_iterator; |
| |
| public: |
| using iterator_category = std::forward_iterator_tag; |
| using value_type = typename std::iterator_traits<It>::value_type; |
| using difference_type = typename std::iterator_traits<It>::difference_type; |
| using pointer = It; |
| using reference = typename std::iterator_traits<It>::reference; |
| |
| constexpr almost_forward_iterator() : it_() {} |
| constexpr explicit almost_forward_iterator(It it) : it_(it) {} |
| template <class U> |
| constexpr almost_forward_iterator(const almost_forward_iterator<U>& u) : it_(u.it_) {} |
| |
| constexpr reference operator*() const { return *it_; } |
| constexpr pointer operator->() const { return it_; } |
| |
| constexpr almost_forward_iterator& operator++() { ++it_; return *this; } |
| // Notice the slightly different return type. |
| constexpr const almost_forward_iterator operator++(int) { return almost_forward_iterator(it_); } |
| |
| friend constexpr bool operator==(const almost_forward_iterator& x, const almost_forward_iterator& y) { |
| return x.it_ == y.it_; |
| } |
| friend constexpr bool operator!=(const almost_forward_iterator& x, const almost_forward_iterator& y) { |
| return x.it_ != y.it_; |
| } |
| }; |
| static_assert(!std::forward_iterator<almost_forward_iterator<int*>>); |
| static_assert( std::input_iterator<almost_forward_iterator<int*>>); |
| |
| struct ForwardOnlyIfNonConstView : std::ranges::view_base { |
| std::string_view view_; |
| |
| constexpr explicit ForwardOnlyIfNonConstView() = default; |
| constexpr ForwardOnlyIfNonConstView(const char* ptr) : view_(ptr) {} |
| constexpr ForwardOnlyIfNonConstView(std::string_view v) : view_(v) {} |
| constexpr ForwardOnlyIfNonConstView(ForwardOnlyIfNonConstView&&) = default; |
| constexpr ForwardOnlyIfNonConstView& operator=(ForwardOnlyIfNonConstView&&) = default; |
| |
| constexpr forward_iterator<std::string_view::const_iterator> begin() { return forward_iterator<std::string_view::const_iterator>(view_.begin()); } |
| constexpr forward_iterator<std::string_view::const_iterator> end() { return forward_iterator<std::string_view::const_iterator>(view_.end()); } |
| constexpr almost_forward_iterator<std::string_view::const_iterator> begin() const { |
| return almost_forward_iterator<std::string_view::const_iterator>(view_.begin()); |
| } |
| constexpr almost_forward_iterator<std::string_view::const_iterator> end() const { |
| return almost_forward_iterator<std::string_view::const_iterator>(view_.end()); |
| } |
| }; |
| static_assert( std::ranges::forward_range<ForwardOnlyIfNonConstView>); |
| static_assert(!std::ranges::forward_range<const ForwardOnlyIfNonConstView>); |
| static_assert( std::ranges::view<ForwardOnlyIfNonConstView>); |
| |
| // InputView |
| |
| struct InputView : std::ranges::view_base { |
| std::string buffer_; |
| |
| constexpr InputView() = default; |
| constexpr InputView(const char* s) : InputView(std::string_view(s)) {} |
| constexpr InputView(std::string_view v) { |
| // Workaround https://github.com/llvm/llvm-project/issues/55867 |
| buffer_ = v; |
| } |
| |
| constexpr cpp20_input_iterator<char*> begin() { return cpp20_input_iterator<char*>(buffer_.begin().base()); } |
| constexpr sentinel_wrapper<cpp20_input_iterator<char*>> end() { |
| return sentinel_wrapper(cpp20_input_iterator<char*>(buffer_.end().base())); |
| } |
| constexpr cpp20_input_iterator<const char*> begin() const { |
| return cpp20_input_iterator<const char*>(buffer_.begin().base()); |
| } |
| constexpr sentinel_wrapper<cpp20_input_iterator<const char*>> end() const { |
| return sentinel_wrapper(cpp20_input_iterator<const char*>(buffer_.end().base())); |
| } |
| friend constexpr bool operator==(const InputView& lhs, const InputView& rhs) { |
| return lhs.buffer_ == rhs.buffer_; |
| } |
| }; |
| |
| static_assert(std::ranges::input_range<InputView>); |
| static_assert(std::ranges::input_range<const InputView>); |
| static_assert(std::ranges::view<InputView>); |
| |
| // ForwardTinyView |
| |
| struct ForwardTinyView : std::ranges::view_base { |
| char c_[1] = {}; |
| constexpr ForwardTinyView() = default; |
| constexpr ForwardTinyView(char c) { *c_ = c; } |
| constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(c_); } |
| constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(c_ + 1); } |
| constexpr static std::size_t size() { return 1; } |
| }; |
| static_assert(std::ranges::forward_range<ForwardTinyView>); |
| static_assert(std::ranges::view<ForwardTinyView>); |
| LIBCPP_STATIC_ASSERT(std::ranges::__tiny_range<ForwardTinyView>); |
| |
| // Aliases |
| |
| using SplitViewCopyable = std::ranges::lazy_split_view<CopyableView, CopyableView>; |
| using OuterIterCopyable = std::ranges::iterator_t<SplitViewCopyable>; |
| using ValueTypeCopyable = OuterIterCopyable::value_type; |
| using InnerIterCopyable = std::ranges::iterator_t<ValueTypeCopyable>; |
| using BaseIterCopyable = std::ranges::iterator_t<CopyableView>; |
| |
| using SplitViewForward = std::ranges::lazy_split_view<ForwardView, ForwardView>; |
| using OuterIterForward = std::ranges::iterator_t<SplitViewForward>; |
| using ValueTypeForward = OuterIterForward::value_type; |
| using InnerIterForward = std::ranges::iterator_t<ValueTypeForward>; |
| using BaseIterForward = std::ranges::iterator_t<ForwardView>; |
| |
| using SplitViewInput = std::ranges::lazy_split_view<InputView, ForwardTinyView>; |
| using OuterIterInput = std::ranges::iterator_t<SplitViewInput>; |
| using ValueTypeInput = OuterIterInput::value_type; |
| using InnerIterInput = std::ranges::iterator_t<ValueTypeInput>; |
| using BaseIterInput = std::ranges::iterator_t<InputView>; |
| |
| using SplitViewDiff = std::ranges::lazy_split_view<ForwardDiffView, ForwardDiffView>; |
| using OuterIterConst = decltype(std::declval<const SplitViewDiff>().begin()); |
| using OuterIterNonConst = decltype(std::declval<SplitViewDiff>().begin()); |
| static_assert(!std::same_as<OuterIterConst, OuterIterNonConst>); |
| using InnerIterConst = decltype((*std::declval<OuterIterConst>()).begin()); |
| using InnerIterNonConst = decltype((*std::declval<OuterIterNonConst>()).begin()); |
| static_assert(!std::same_as<InnerIterConst, InnerIterNonConst>); |
| |
| #endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_LAZY_SPLIT_TYPES_H |