]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/std/ranges/access/rbegin.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / std / ranges / access / rbegin.cc
1 // Copyright (C) 2019-2024 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-do run { target c++20 } }
19
20 #include <ranges>
21 #include <testsuite_hooks.h>
22 #include <testsuite_iterators.h>
23
24 static_assert(__gnu_test::is_customization_point_object(std::ranges::rbegin));
25
26 struct R1
27 {
28 int i = 0;
29 int j = 0;
30
31 constexpr const int* rbegin() const { return &i; }
32 friend constexpr const int* rbegin(const R1&& r) { return &r.j; }
33 };
34
35 // N.B. this is a lie, rbegin on an R1 rvalue will return a dangling pointer.
36 template<> constexpr bool std::ranges::enable_borrowed_range<R1> = true;
37
38 void
39 test01()
40 {
41 constexpr R1 r;
42 // decay-copy(t.rbegin()) if it is a valid expression
43 // and its type I models input_or_output_iterator.
44 static_assert( std::ranges::rbegin(r) == &r.i );
45 static_assert( std::ranges::rbegin(std::move(r)) == &r.i );
46 }
47
48 struct R2
49 {
50 int a[2] = { };
51
52 constexpr const int* begin() const { return a; }
53 constexpr const int* end() const { return a + 2; }
54
55 friend constexpr const long* begin(const R2&&); // not defined
56 friend constexpr const long* end(const R2&&); // not defined
57 };
58
59 // N.B. this is a lie, begin/end on an R2 rvalue will return a dangling pointer.
60 template<> constexpr bool std::ranges::enable_borrowed_range<R2> = true;
61
62 void
63 test02()
64 {
65 constexpr R2 r;
66 // Otherwise, decay-copy(rbegin(t)) if it is a valid expression
67 // and its type I models input_or_output_iterator [...]
68 static_assert( std::ranges::rbegin(r)
69 == std::make_reverse_iterator(std::ranges::end(r)) );
70 static_assert( std::ranges::rbegin(std::move(r))
71 == std::make_reverse_iterator(std::ranges::end(std::move(r))) );
72 }
73
74 void
75 test03()
76 {
77 struct R3
78 : __gnu_test::test_range<int, __gnu_test::bidirectional_iterator_wrapper>
79 {
80 R3(int (&a)[2]) : test_range(a) { }
81
82 using test_range::begin;
83
84 // Replace test_range::end() to return same type as begin()
85 // so ranges::rbegin will wrap it in a reverse_iterator .
86 auto end() &
87 {
88 using __gnu_test::bidirectional_iterator_wrapper;
89 return bidirectional_iterator_wrapper<int>(bounds.last, &bounds);
90 }
91 };
92
93 int a[2] = { };
94 R3 r(a);
95
96 // Otherwise, make_reverse_iterator(ranges::end(t)) if both ranges::begin(t)
97 // and ranges::end(t) are valid expressions of the same type I which models
98 // bidirectional_iterator.
99
100 VERIFY( std::ranges::rbegin(r) == std::make_reverse_iterator(std::ranges::end(r)) );
101 }
102
103 int
104 main()
105 {
106 test01();
107 test02();
108 test03();
109 }