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
24template<class T>
25concept BeginInvocable = requires(std::ranges::drop_view<T> t) { t.begin(); };
26
27template <bool IsSimple>
28struct 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
44using SimpleView = MaybeSimpleView<true>;
45using NonSimpleView = MaybeSimpleView<false>;
46
47constexpr 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
156int main(int, char**) {
157 test();
158 static_assert(test());
159
160 return 0;
161}
162

source code of libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp