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>
33template <class T>
34concept HasEnd = requires(T t) { t.end(); };
35
36template <class T>
37concept HasConstEnd = requires(const T ct) { ct.end(); };
38
39struct 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
45static_assert(HasEnd<std::ranges::elements_view<NoConstEndView, 0>>);
46static_assert(!HasConstEnd<std::ranges::elements_view<NoConstEndView, 0>>);
47
48constexpr 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
138int main(int, char**) {
139 test();
140 static_assert(test());
141 return 0;
142}
143

source code of libcxx/test/std/ranges/range.adaptors/range.elements/end.pass.cpp