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 end() requires (!simple-view<V> && !common_range<V>) |
12 | // constexpr auto end() requires (!simple-view<V> && common_range<V>) |
13 | // constexpr auto end() const requires range<const V> |
14 | // constexpr auto end() const requires common_range<const V> |
15 | |
16 | #include <cassert> |
17 | #include <iterator> |
18 | #include <ranges> |
19 | #include <type_traits> |
20 | #include <utility> |
21 | |
22 | #include "types.h" |
23 | |
24 | // | simple | common | v.end() | as_const(v) |
25 | // | | | | .end() |
26 | // |--------|--------|------------------|--------------- |
27 | // | Y | Y | iterator<true> | iterator<true> |
28 | // | Y | N | sentinel<true> | sentinel<true> |
29 | // | N | Y | iterator<false> | iterator<true> |
30 | // | N | N | sentinel<false> | sentinel<true> |
31 | |
32 | // !range<const V> |
33 | template <class T> |
34 | concept HasEnd = requires(T t) { t.end(); }; |
35 | |
36 | template <class T> |
37 | concept HasConstEnd = requires(const T ct) { ct.end(); }; |
38 | |
39 | struct NoConstEndView : TupleBufferView { |
40 | using TupleBufferView::TupleBufferView; |
41 | constexpr std::tuple<int>* begin() { return buffer_; } |
42 | constexpr std::tuple<int>* end() { return buffer_ + size_; } |
43 | }; |
44 | |
45 | static_assert(HasEnd<std::ranges::elements_view<NoConstEndView, 0>>); |
46 | static_assert(!HasConstEnd<std::ranges::elements_view<NoConstEndView, 0>>); |
47 | |
48 | constexpr bool test() { |
49 | std::tuple<int> buffer[] = {{1}, {2}, {3}}; |
50 | |
51 | // simple-view && common_view |
52 | { |
53 | SimpleCommon v{buffer}; |
54 | auto ev = std::views::elements<0>(v); |
55 | |
56 | auto it = ev.begin(); |
57 | decltype(auto) st = ev.end(); |
58 | assert(st == it + 3); |
59 | |
60 | auto const_it = std::as_const(ev).begin(); |
61 | decltype(auto) const_st = std::as_const(ev).end(); |
62 | assert(const_st == const_it + 3); |
63 | |
64 | // Both iterator<true> |
65 | static_assert(std::same_as<decltype(st), decltype(const_st)>); |
66 | static_assert(std::same_as<decltype(st), decltype(it)>); |
67 | static_assert(std::same_as<decltype(const_st), decltype(const_it)>); |
68 | } |
69 | |
70 | // simple-view && !common_view |
71 | { |
72 | SimpleNonCommon v{buffer}; |
73 | auto ev = std::views::elements<0>(v); |
74 | |
75 | auto it = ev.begin(); |
76 | decltype(auto) st = ev.end(); |
77 | assert(st == it + 3); |
78 | |
79 | auto const_it = std::as_const(ev).begin(); |
80 | decltype(auto) const_st = std::as_const(ev).end(); |
81 | assert(const_st == const_it + 3); |
82 | |
83 | // Both iterator<true> |
84 | static_assert(std::same_as<decltype(st), decltype(const_st)>); |
85 | static_assert(!std::same_as<decltype(st), decltype(it)>); |
86 | static_assert(!std::same_as<decltype(const_st), decltype(const_it)>); |
87 | } |
88 | |
89 | // !simple-view && common_view |
90 | { |
91 | NonSimpleCommon v{buffer}; |
92 | auto ev = std::views::elements<0>(v); |
93 | |
94 | auto it = ev.begin(); |
95 | decltype(auto) st = ev.end(); |
96 | assert(st == it + 3); |
97 | |
98 | auto const_it = std::as_const(ev).begin(); |
99 | decltype(auto) const_st = std::as_const(ev).end(); |
100 | assert(const_st == const_it + 3); |
101 | |
102 | // iterator<false> and iterator<true> |
103 | static_assert(!std::same_as<decltype(st), decltype(const_st)>); |
104 | static_assert(std::same_as<decltype(st), decltype(it)>); |
105 | static_assert(std::same_as<decltype(const_st), decltype(const_it)>); |
106 | } |
107 | |
108 | // !simple-view && !common_view |
109 | { |
110 | NonSimpleNonCommon v{buffer}; |
111 | auto ev = std::views::elements<0>(v); |
112 | |
113 | auto it = ev.begin(); |
114 | decltype(auto) st = ev.end(); |
115 | assert(st == it + 3); |
116 | |
117 | auto const_it = std::as_const(ev).begin(); |
118 | decltype(auto) const_st = std::as_const(ev).end(); |
119 | assert(const_st == const_it + 3); |
120 | |
121 | // sentinel<false> and sentinel<true> |
122 | static_assert(!std::same_as<decltype(st), decltype(const_st)>); |
123 | static_assert(!std::same_as<decltype(st), decltype(it)>); |
124 | static_assert(!std::same_as<decltype(const_st), decltype(const_it)>); |
125 | } |
126 | |
127 | // LWG 3406 elements_view::begin() and elements_view::end() have incompatible constraints |
128 | { |
129 | std::tuple<int, int> x[] = {{0, 0}}; |
130 | std::ranges::subrange r = {std::counted_iterator(x, 1), std::default_sentinel}; |
131 | auto v = r | std::views::elements<0>; |
132 | assert(v.begin() != v.end()); |
133 | } |
134 | |
135 | return true; |
136 | } |
137 | |
138 | int main(int, char**) { |
139 | test(); |
140 | static_assert(test()); |
141 | return 0; |
142 | } |
143 | |