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