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() requires (!simple-view<V>); |
12 | // constexpr auto begin() const requires range<const V>; |
13 | |
14 | #include <cassert> |
15 | #include <ranges> |
16 | #include <utility> |
17 | |
18 | #include "test_macros.h" |
19 | #include "test_iterators.h" |
20 | #include "test_range.h" |
21 | #include "types.h" |
22 | |
23 | struct NonCommonSimpleView : std::ranges::view_base { |
24 | int* begin() const; |
25 | sentinel_wrapper<int*> end() const; |
26 | std::size_t size() { return 0; } // deliberately non-const |
27 | }; |
28 | static_assert(std::ranges::sized_range<NonCommonSimpleView>); |
29 | static_assert(!std::ranges::sized_range<const NonCommonSimpleView>); |
30 | |
31 | using CommonInputIterPtrConstInt = common_input_iterator<const int*>; |
32 | using CountedCommonInputIterPtrConstInt = std::counted_iterator<CommonInputIterPtrConstInt>; |
33 | |
34 | constexpr bool test() { |
35 | int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; |
36 | |
37 | // simple-view<V> && sized_range<V> && random_access_range<V> |
38 | { |
39 | using ViewTested = SizedRandomAccessView; |
40 | static_assert(simple_view<ViewTested>); |
41 | static_assert(std::ranges::sized_range<ViewTested>); |
42 | static_assert(std::ranges::random_access_range<ViewTested>); |
43 | |
44 | std::ranges::take_view<ViewTested> tv(ViewTested(buffer), 4); |
45 | assert(tv.begin() == ViewTested(buffer).begin()); |
46 | ASSERT_SAME_TYPE(decltype(tv.begin()), RandomAccessIter); |
47 | |
48 | const std::ranges::take_view<ViewTested> ctv(ViewTested(buffer), 4); |
49 | assert(ctv.begin() == ViewTested(buffer).begin()); |
50 | ASSERT_SAME_TYPE(decltype(ctv.begin()), RandomAccessIter); |
51 | } |
52 | |
53 | // simple-view<V> && sized_range<V> && !random_access_range<V> |
54 | { |
55 | using ViewTested = SizedForwardView; |
56 | static_assert(simple_view<ViewTested>); |
57 | static_assert(std::ranges::sized_range<ViewTested>); |
58 | static_assert(!std::ranges::random_access_range<ViewTested>); |
59 | |
60 | std::ranges::take_view<ViewTested> tv(ViewTested{buffer}, 16); // underlying size is 8 |
61 | assert(tv.begin() == std::counted_iterator<ForwardIter>(ForwardIter(buffer), 8)); // expect min(8, 16) |
62 | ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator<ForwardIter>); |
63 | |
64 | const std::ranges::take_view<ViewTested> ctv(ViewTested{buffer}, 4); |
65 | assert(ctv.begin() == std::counted_iterator<ForwardIter>(ForwardIter(buffer), 4)); |
66 | ASSERT_SAME_TYPE(decltype(ctv.begin()), std::counted_iterator<ForwardIter>); |
67 | } |
68 | |
69 | // simple-view<V> && !sized_range<V> |
70 | { |
71 | using ViewTested = MoveOnlyView; |
72 | static_assert(simple_view<ViewTested>); |
73 | std::ranges::take_view<ViewTested> tv(ViewTested{buffer}, 4); |
74 | assert(tv.begin() == std::counted_iterator<int*>(buffer, 4)); |
75 | ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator<int*>); |
76 | |
77 | const std::ranges::take_view<ViewTested> ctv(ViewTested{buffer}, 4); |
78 | assert(ctv.begin() == std::counted_iterator<int*>(buffer, 4)); |
79 | ASSERT_SAME_TYPE(decltype(ctv.begin()), std::counted_iterator<int*>); |
80 | } |
81 | |
82 | // simple-view<V> && sized_range<V> && !sized_range<const V> |
83 | { |
84 | using ViewTested = NonCommonSimpleView; |
85 | static_assert(simple_view<ViewTested>); |
86 | static_assert(std::ranges::sized_range<ViewTested>); |
87 | static_assert(!std::ranges::sized_range<const ViewTested>); |
88 | |
89 | std::ranges::take_view<ViewTested> tv{}; |
90 | ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator<int*>); |
91 | ASSERT_SAME_TYPE(decltype(std::as_const(tv).begin()), std::counted_iterator<int*>); |
92 | } |
93 | |
94 | // !simple-view<V> && !sized_range<V> |
95 | { |
96 | using ViewTested = NonSimpleNonSizedView; |
97 | static_assert(!simple_view<ViewTested>); |
98 | static_assert(!std::ranges::sized_range<ViewTested>); |
99 | |
100 | std::ranges::take_view<ViewTested> tv{ViewTested{buffer, buffer + 2}, 4}; |
101 | // The count for the counted iterator is the count of the take_view (i.e., 4) |
102 | assert(tv.begin() == CountedCommonInputIterPtrConstInt(CommonInputIterPtrConstInt(buffer), 4)); |
103 | ASSERT_SAME_TYPE(decltype(tv.begin()), CountedCommonInputIterPtrConstInt); |
104 | } |
105 | |
106 | // !simple-view<V> && sized_range<V> |
107 | { |
108 | using ViewTested = NonSimpleSizedView; |
109 | static_assert(!simple_view<ViewTested>); |
110 | static_assert(std::ranges::sized_range<ViewTested>); |
111 | |
112 | std::ranges::take_view<ViewTested> tv{ViewTested{buffer, buffer + 2}, 4}; |
113 | // The count for the counted iterator is the min(2, 4) (i.e., 2). |
114 | assert(tv.begin() == CountedCommonInputIterPtrConstInt(CommonInputIterPtrConstInt(buffer), 2)); |
115 | ASSERT_SAME_TYPE(decltype(tv.begin()), CountedCommonInputIterPtrConstInt); |
116 | } |
117 | |
118 | // !simple-view<V> && sized_range<V> && random_access_range<V> |
119 | { |
120 | using ViewTested = NonSimpleSizedRandomView; |
121 | static_assert(!simple_view<ViewTested>); |
122 | static_assert(std::ranges::sized_range<ViewTested>); |
123 | static_assert(std::ranges::random_access_range<ViewTested>); |
124 | |
125 | std::ranges::take_view<ViewTested> tv{ViewTested{buffer, buffer + 2}, 4}; |
126 | assert(tv.begin() == random_access_iterator<const int*>(buffer)); |
127 | ASSERT_SAME_TYPE(decltype(tv.begin()), random_access_iterator<const int*>); |
128 | } |
129 | return true; |
130 | } |
131 | |
132 | int main(int, char**) { |
133 | test(); |
134 | static_assert(test()); |
135 | |
136 | return 0; |
137 | } |
138 | |