xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.elements/end.pass.cpp (revision 94461822c75d5080bf648f86552f7a59b76905c9)
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