]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/std/ranges/access/cend.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / std / ranges / access / cend.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 <utility> // as_const
23 #include <testsuite_hooks.h>
24 #include <testsuite_iterators.h>
25
26 static_assert(__gnu_test::is_customization_point_object(std::ranges::cend));
27
28 using std::same_as;
29
30 void
31 test01()
32 {
33 int a[2] = {};
34
35 static_assert(same_as<decltype(std::ranges::cend(a)), const int*>);
36 static_assert(noexcept(std::ranges::cend(a)));
37 VERIFY( std::ranges::cend(a) == (a + 2) );
38 }
39
40 struct R
41 {
42 int a[4] = { 0, 1, 2, 3 };
43
44 const int* begin() const { return nullptr; }
45 friend const int* begin(const R&& r) noexcept { return nullptr; }
46
47 // Should be ignored because it doesn't return a sentinel for int*
48 const long* end() const { return nullptr; }
49
50 friend int* end(R& r) { return r.a + 0; }
51 friend int* end(R&& r) { return r.a + 1; }
52 friend const int* end(const R& r) noexcept { return r.a + 2; }
53 friend const int* end(const R&& r) noexcept { return r.a + 3; }
54 };
55
56 struct RV // view on an R
57 {
58 R& r;
59
60 friend const int* begin(RV& rv) { return rv.r.begin(); }
61 friend int* end(RV& rv) { return end(rv.r); }
62 friend const int* begin(const RV& rv) noexcept { return rv.r.begin(); }
63 friend const int* end(const RV& rv) noexcept { return end(std::as_const(rv.r)); }
64 };
65
66 // Allow ranges::end to work with RV&&
67 template<> constexpr bool std::ranges::enable_borrowed_range<RV> = true;
68
69 void
70 test03()
71 {
72 R r;
73 const R& c = r;
74 VERIFY( std::ranges::cend(r) == std::ranges::end(c) );
75 VERIFY( std::ranges::cend(c) == std::ranges::end(c) );
76
77 RV v{r};
78 const RV cv{r};
79 VERIFY( std::ranges::cend(std::move(v)) == std::ranges::end(c) );
80 VERIFY( std::ranges::cend(std::move(cv)) == std::ranges::end(c) );
81 }
82
83 struct RR
84 {
85 short s = 0;
86 long l = 0;
87 int a[4] = { 0, 1, 2, 3 };
88
89 const void* begin() const; // return type not an iterator
90
91 friend int* end(RR&) { throw 1; }
92 short* end() noexcept { return &s; }
93
94 friend const long* begin(const RR&) noexcept;
95 const long* end() const { return &l; }
96
97 friend int* begin(RR&&) noexcept;
98 friend int* end(RR&& r) { return r.a + 1; }
99
100 friend const int* begin(const RR&&) noexcept;
101 friend const int* end(const RR&& r) noexcept { return r.a + 3; }
102 };
103
104 // N.B. this is a lie, begin/end on an RR rvalue will return a dangling pointer.
105 template<> constexpr bool std::ranges::enable_borrowed_range<RR> = true;
106
107 void
108 test04()
109 {
110 RR r;
111 const RR& c = r;
112 VERIFY( std::ranges::cend(r) == std::ranges::end(c) );
113 VERIFY( std::ranges::cend(c) == std::ranges::end(c) );
114
115 VERIFY( std::ranges::cend(std::move(r)) == std::ranges::end(c) );
116 VERIFY( std::ranges::cend(std::move(c)) == std::ranges::end(c) );
117 }
118
119 int
120 main()
121 {
122 test01();
123 test03();
124 test04();
125 }