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;
beginNoConstEndView41 constexpr std::tuple<int>* begin() { return buffer_; }
endNoConstEndView42 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
test()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
main(int,char **)138 int main(int, char**) {
139 test();
140 static_assert(test());
141 return 0;
142 }
143