]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/std/ranges/adaptors/filter.cc
libstdc++: Make copyable-box completely constexpr (LWG 3572)
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / std / ranges / adaptors / filter.cc
1 // Copyright (C) 2020-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 <algorithm>
22 #include <ranges>
23 #include <testsuite_hooks.h>
24 #include <testsuite_iterators.h>
25
26 using __gnu_test::test_range;
27 using __gnu_test::bidirectional_iterator_wrapper;
28 using __gnu_test::forward_iterator_wrapper;
29 using __gnu_test::random_access_iterator_wrapper;
30
31 namespace ranges = std::ranges;
32 namespace views = std::ranges::views;
33
34 void
35 test01()
36 {
37 int x[] = {1,2,3,4,5,6};
38 auto is_odd = [] (int i) { return i%2==1; };
39 auto v = x | views::filter(is_odd);
40 using R = decltype(v);
41 static_assert(std::same_as<int&, decltype(*v.begin())>);
42 static_assert(ranges::view<R>);
43 static_assert(ranges::input_range<R>);
44 static_assert(ranges::common_range<R>);
45 static_assert(!ranges::sized_range<R>);
46 static_assert(ranges::bidirectional_range<R>);
47 static_assert(!ranges::random_access_range<R>);
48 static_assert(ranges::range<views::all_t<R>>);
49 VERIFY( ranges::equal(v, (int[]){1,3,5}) );
50 VERIFY( ranges::equal(v | views::reverse, (int[]){5,3,1}) );
51 VERIFY( v.pred()(3) == true );
52 VERIFY( v.pred()(4) == false );
53 }
54
55 void
56 test02()
57 {
58 int x[] = {1,2,3,4,5,6};
59 auto f = [flag=false] (int) mutable { return flag = !flag; };
60 auto v = views::filter(f)(x);
61 using R = decltype(v);
62 static_assert(std::same_as<int&, decltype(*v.begin())>);
63 static_assert(ranges::range<R>);
64 static_assert(std::copyable<R>);
65 static_assert(!ranges::view<const R>);
66 VERIFY( ranges::equal(v, (int[]){1,3,5}) );
67 }
68
69 struct X
70 {
71 int i, j;
72 };
73
74 void
75 test03()
76 {
77 X x[] = {{1,3}, {2,5}, {3,7}, {4,9}};
78 test_range<X, bidirectional_iterator_wrapper> rx(x);
79 auto v = rx | views::filter([] (auto&& p) { return p.i%2==0; });
80 int sum = 0;
81 for (auto i = v.begin(); i != v.end(); ++i)
82 sum += i->j;
83 VERIFY( sum == 14 );
84 }
85
86 void
87 test04()
88 {
89 auto yes = [] (int) { return true; };
90 VERIFY( ranges::equal(views::iota(0) | views::filter(yes) | views::take(1),
91 (int[]){0}) );
92 }
93
94 // The following tests that filter_view::begin caches its result.
95
96 template<template<typename> typename wrapper>
97 struct test_view : ranges::view_base
98 {
99 bool begin_already_called = false;
100 static inline int x[] = {1,2,3,4,5};
101 test_range<int, wrapper> rx{x};
102
103 auto
104 begin()
105 {
106 if (begin_already_called)
107 x[0] = 10;
108 begin_already_called = true;
109 return rx.begin();
110 }
111
112 auto
113 end()
114 { return rx.end(); }
115 };
116
117 template<template<typename> typename wrapper>
118 void
119 test05()
120 {
121 auto v = test_view<wrapper>{} | views::filter([] (int i) { return i%2 == 0; });
122 VERIFY( ranges::equal(v, (int[]){2,4}) );
123 VERIFY( ranges::equal(v, (int[]){2,4}) );
124 }
125
126 template<auto filter = views::filter>
127 void
128 test06()
129 {
130 // Verify SFINAE behavior.
131 extern int x[5];
132 auto p = [] (int*) { return true; };
133 static_assert(!requires { filter(); });
134 static_assert(!requires { filter(x, p, p); });
135 static_assert(!requires { filter(x, p); });
136 static_assert(!requires { filter(p)(x); });
137 static_assert(!requires { x | (filter(p) | views::all); });
138 static_assert(!requires { (filter(p) | views::all)(x); });
139 static_assert(!requires { filter | views::all; });
140 static_assert(!requires { views::all | filter; });
141 }
142
143 constexpr bool
144 test07()
145 {
146 struct Pred
147 {
148 constexpr Pred() { }
149 constexpr Pred(const Pred&) { }
150 constexpr Pred(Pred&&) { }
151 // These make it non-copyable, so non-copyable-box<Pred> will provide
152 // assignment.
153 Pred& operator=(const Pred&) = delete;
154 Pred& operator=(Pred&&) = delete;
155
156 bool operator()(int i) const { return i < 10; }
157 };
158
159 int i = 0;
160 ranges::filter_view v(views::single(i), Pred{});
161 // LWG 3572. copyable-box should be fully constexpr
162 v = v;
163 v = std::move(v);
164
165 return true;
166 }
167
168 static_assert( test07() );
169
170 int
171 main()
172 {
173 test01();
174 test02();
175 test03();
176 test04();
177 test05<forward_iterator_wrapper>();
178 test05<random_access_iterator_wrapper>();
179 test06();
180 test07();
181 }