1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 11 // constexpr auto begin() 12 // requires (!(simple-view<V> && 13 // random_access_range<const V> && sized_range<const V>)); 14 // constexpr auto begin() const 15 // requires random_access_range<const V> && sized_range<const V>; 16 17 #include <ranges> 18 19 #include "test_macros.h" 20 #include "test_iterators.h" 21 #include "test_range.h" 22 #include "types.h" 23 24 template<class T> 25 concept BeginInvocable = requires(std::ranges::drop_view<T> t) { t.begin(); }; 26 27 template <bool IsSimple> 28 struct MaybeSimpleView : std::ranges::view_base { 29 int* num_of_non_const_begin_calls; 30 int* num_of_const_begin_calls; 31 32 constexpr int* begin() { 33 ++(*num_of_non_const_begin_calls); 34 return nullptr; 35 } 36 constexpr std::conditional_t<IsSimple, int*, const int*> begin() const { 37 ++(*num_of_const_begin_calls); 38 return nullptr; 39 } 40 constexpr int* end() const { return nullptr; } 41 constexpr std::size_t size() const { return 0; } 42 }; 43 44 using SimpleView = MaybeSimpleView<true>; 45 using NonSimpleView = MaybeSimpleView<false>; 46 47 constexpr bool test() { 48 // random_access_range<const V> && sized_range<const V> 49 std::ranges::drop_view dropView1(MoveOnlyView(), 4); 50 assert(dropView1.begin() == globalBuff + 4); 51 52 // !random_access_range<const V> 53 std::ranges::drop_view dropView2(ForwardView(), 4); 54 assert(base(dropView2.begin()) == globalBuff + 4); 55 56 // !random_access_range<const V> 57 std::ranges::drop_view dropView3(InputView(), 4); 58 assert(base(dropView3.begin()) == globalBuff + 4); 59 60 // random_access_range<const V> && sized_range<const V> 61 std::ranges::drop_view dropView4(MoveOnlyView(), 8); 62 assert(dropView4.begin() == globalBuff + 8); 63 64 // random_access_range<const V> && sized_range<const V> 65 std::ranges::drop_view dropView5(MoveOnlyView(), 0); 66 assert(dropView5.begin() == globalBuff); 67 68 // random_access_range<const V> && sized_range<const V> 69 const std::ranges::drop_view dropView6(MoveOnlyView(), 0); 70 assert(dropView6.begin() == globalBuff); 71 72 // random_access_range<const V> && sized_range<const V> 73 std::ranges::drop_view dropView7(MoveOnlyView(), 10); 74 assert(dropView7.begin() == globalBuff + 8); 75 76 IteratorOpCounts opcounts; 77 CountedView view8(&opcounts); 78 ; 79 std::ranges::drop_view dropView8(view8, 5); 80 assert(base(base(dropView8.begin())) == globalBuff + 5); 81 assert(opcounts.increments == 5); 82 83 static_assert(!BeginInvocable<const ForwardView>); 84 85 { 86 // non-common non-simple view, 87 // The wording of the standard is: 88 // Returns: ranges::next(ranges::begin(base_), count_, ranges::end(base_)) 89 // Note that "Returns" is used here, meaning that we don't have to do it this way. 90 // In fact, this will use ranges::advance that has O(n) on non-common range. 91 // but [range.range] requires "amortized constant time" for ranges::begin and ranges::end 92 // Here, we test that begin() is indeed constant time, by creating a customized 93 // sentinel and counting how many times the sentinel eq function is called. 94 // It should be 0 times, but since this test (or any test under libcxx/test/std) is 95 // also used by other implementations, we relax the condition to that 96 // sentinel_cmp_calls is a constant number. 97 int sentinel_cmp_calls_1 = 0; 98 int sentinel_cmp_calls_2 = 0; 99 using NonCommonView = MaybeSimpleNonCommonView<false>; 100 static_assert(std::ranges::random_access_range<NonCommonView>); 101 static_assert(std::ranges::sized_range<NonCommonView>); 102 std::ranges::drop_view dropView9_1(NonCommonView{{}, 0, &sentinel_cmp_calls_1}, 4); 103 std::ranges::drop_view dropView9_2(NonCommonView{{}, 0, &sentinel_cmp_calls_2}, 6); 104 assert(dropView9_1.begin() == globalBuff + 4); 105 assert(dropView9_2.begin() == globalBuff + 6); 106 assert(sentinel_cmp_calls_1 == sentinel_cmp_calls_2); 107 } 108 109 { 110 // non-common simple view, same as above. 111 int sentinel_cmp_calls_1 = 0; 112 int sentinel_cmp_calls_2 = 0; 113 using NonCommonView = MaybeSimpleNonCommonView<true>; 114 static_assert(std::ranges::random_access_range<NonCommonView>); 115 static_assert(std::ranges::sized_range<NonCommonView>); 116 std::ranges::drop_view dropView10_1(NonCommonView{{}, 0, &sentinel_cmp_calls_1}, 4); 117 std::ranges::drop_view dropView10_2(NonCommonView{{}, 0, &sentinel_cmp_calls_2}, 6); 118 assert(dropView10_1.begin() == globalBuff + 4); 119 assert(dropView10_2.begin() == globalBuff + 6); 120 assert(sentinel_cmp_calls_1 == sentinel_cmp_calls_2); 121 } 122 123 { 124 static_assert(std::ranges::random_access_range<const SimpleView>); 125 static_assert(std::ranges::sized_range<const SimpleView>); 126 static_assert(simple_view<SimpleView>); 127 int non_const_calls = 0; 128 int const_calls = 0; 129 std::ranges::drop_view dropView(SimpleView{{}, &non_const_calls, &const_calls}, 4); 130 assert(dropView.begin() == nullptr); 131 assert(non_const_calls == 0); 132 assert(const_calls == 1); 133 assert(std::as_const(dropView).begin() == nullptr); 134 assert(non_const_calls == 0); 135 assert(const_calls == 2); 136 } 137 138 { 139 static_assert(std::ranges::random_access_range<const NonSimpleView>); 140 static_assert(std::ranges::sized_range<const NonSimpleView>); 141 static_assert(!simple_view<NonSimpleView>); 142 int non_const_calls = 0; 143 int const_calls = 0; 144 std::ranges::drop_view dropView(NonSimpleView{{}, &non_const_calls, &const_calls}, 4); 145 assert(dropView.begin() == nullptr); 146 assert(non_const_calls == 1); 147 assert(const_calls == 0); 148 assert(std::as_const(dropView).begin() == nullptr); 149 assert(non_const_calls == 1); 150 assert(const_calls == 1); 151 } 152 153 return true; 154 } 155 156 int main(int, char**) { 157 test(); 158 static_assert(test()); 159 160 return 0; 161 } 162