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