]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/std/ranges/access/rend.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / std / ranges / access / rend.cc
1 // Copyright (C) 2019-2023 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
17
18 // { dg-options "-std=gnu++2a" }
19 // { dg-do run { target c++2a } }
20
21 #include <ranges>
22 #include <testsuite_hooks.h>
23 #include <testsuite_iterators.h>
24
25 static_assert(__gnu_test::is_customization_point_object(std::ranges::rend));
26
27 struct R1
28 {
29 int i = 0;
30 int j = 0;
31
32 constexpr const int* rbegin() const { return &i; }
33 constexpr const int* rend() const { return &i + 1; }
34 friend constexpr const int* rbegin(const R1&&); // not defined
35 friend constexpr const int* rend(const R1&&); // not defined
36 };
37
38 // N.B. this is a lie, rend on an R1 rvalue will return a dangling pointer.
39 template<> constexpr bool std::ranges::enable_borrowed_range<R1> = true;
40
41 void
42 test01()
43 {
44 constexpr R1 r;
45
46 // decay-copy(t.rend()) if it is a valid expression
47 // and its type S models sentinel_for<decltype(ranges::rbegin(E))>
48
49 static_assert( std::ranges::rend(r) == &r.i + 1 );
50 static_assert( std::ranges::rend(std::move(r)) == &r.i + 1 );
51 }
52
53 struct R2
54 {
55 int i = 0;
56
57 int* rbegin() noexcept { return &i + 1; }
58 long* rend() noexcept { return nullptr; } // not a sentinel for rbegin()
59
60 friend long* rbegin(R2&) noexcept { return nullptr; }
61 friend int* rend(R2& r) { return &r.i; }
62 };
63
64 void
65 test02()
66 {
67 R2 r;
68
69 // Otherwise, decay-copy(rend(t)) if it is a valid expression
70 // and its type S models sentinel_for<decltype(ranges::rbegin(E))>
71
72 auto i1 = std::ranges::rbegin(r);
73 auto i2 = rend(r);
74 static_assert( std::sentinel_for<decltype(i2), decltype(i1)> );
75 VERIFY( std::ranges::rend(r) == &r.i );
76 static_assert( !noexcept(std::ranges::rend(r)) );
77 }
78
79 struct R3
80 {
81 int a[2] = { };
82 long l[2] = { };
83
84 constexpr const int* begin() const { return a; }
85 constexpr const int* end() const { return a + 2; }
86
87 friend constexpr const long* begin(const R3&& r) { return r.l; }
88 friend constexpr const long* end(const R3&& r) { return r.l + 2; }
89 };
90
91 // N.B. this is a lie, begin/end on an R3 rvalue will return a dangling pointer.
92 template<> constexpr bool std::ranges::enable_borrowed_range<R3> = true;
93
94 void
95 test03()
96 {
97 constexpr R3 r;
98
99 // Otherwise, make_reverse_iterator(ranges::begin(t)) if both
100 // ranges::begin(t) and ranges::end(t) are valid expressions
101 // of the same type I which models bidirectional_iterator.
102
103 static_assert( std::ranges::rend(r)
104 == std::make_reverse_iterator(std::ranges::begin(r)) );
105 static_assert( std::ranges::rend(std::move(r))
106 == std::make_reverse_iterator(std::ranges::begin(std::move(r))) );
107 }
108
109 void
110 test04()
111 {
112 struct R4
113 : __gnu_test::test_range<int, __gnu_test::bidirectional_iterator_wrapper>
114 {
115 R4(int (&a)[2]) : test_range(a) { }
116
117 using test_range::begin;
118
119 // Replace test_range::end() to return same type as begin()
120 // so ranges::rend will wrap it in a reverse_iterator.
121 auto end() &
122 {
123 using __gnu_test::bidirectional_iterator_wrapper;
124 return bidirectional_iterator_wrapper<int>(bounds.last, &bounds);
125 }
126 };
127
128 int a[2] = { };
129 R4 r(a);
130 VERIFY( std::ranges::rend(r) == std::make_reverse_iterator(std::ranges::begin(r)) );
131 }
132
133 int
134 main()
135 {
136 test01();
137 test02();
138 test03();
139 test04();
140 }