]> 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-2020 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 struct R1
26 {
27 int i = 0;
28 int j = 0;
29
30 constexpr const int* rbegin() const { return &i; }
31 constexpr const int* rend() const { return &i + 1; }
32 friend constexpr const int* rbegin(const R1&&); // not defined
33 friend constexpr const int* rend(const R1&&); // not defined
34 };
35
36 // N.B. this is a lie, rend on an R1 rvalue will return a dangling pointer.
37 template<> constexpr bool std::ranges::enable_safe_range<R1> = true;
38
39 void
40 test01()
41 {
42 constexpr R1 r;
43 static_assert( std::ranges::rend(r) == &r.i + 1 );
44 static_assert( std::ranges::rend(std::move(r)) == &r.i + 1 );
45 }
46
47 struct R2
48 {
49 int a[2] = { };
50 long l[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&& r) { return r.l; }
56 friend constexpr const long* end(const R2&& r) { return r.l + 2; }
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_safe_range<R2> = true;
61
62 void
63 test02()
64 {
65 constexpr R2 r;
66 static_assert( std::ranges::rend(r)
67 == std::make_reverse_iterator(std::ranges::begin(r)) );
68 static_assert( std::ranges::rend(std::move(r))
69 == std::make_reverse_iterator(std::ranges::begin(std::move(r))) );
70 }
71
72 struct R3
73 {
74 int i = 0;
75
76 int* rbegin() noexcept { return &i + 1; }
77 long* rend() noexcept { return nullptr; } // not a sentinel for rbegin()
78
79 friend long* rbegin(R3&) noexcept { return nullptr; }
80 friend int* rend(R3& r) { return &r.i; }
81 };
82
83 void
84 test03()
85 {
86 R3 r;
87 auto i1 = std::ranges::rbegin(r);
88 auto i2 = rend(r);
89 static_assert( std::sentinel_for<decltype(i2), decltype(i1)> );
90 // VERIFY( std::ranges::rend(r) == r.i );
91 // static_assert( !noexcept(std::ranges::rend(r)) );
92 }
93
94 void
95 test04()
96 {
97 using __gnu_test::test_range;
98 using __gnu_test::bidirectional_iterator_wrapper;
99
100 int a[2] = { };
101 test_range<int, bidirectional_iterator_wrapper> r(a);
102 VERIFY( std::ranges::rend(r) == std::make_reverse_iterator(std::ranges::begin(r)) );
103 }
104
105 int
106 main()
107 {
108 test01();
109 test02();
110 test03();
111 }