1 // Copyright (C) 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 <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
test01()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
test02()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
test03()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
test04()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
begintest_view104 begin()
105 {
106 if (begin_already_called)
107 x[0] = 10;
108 begin_already_called = true;
109 return rx.begin();
110 }
111
112 auto
endtest_view113 end()
114 { return rx.end(); }
115 };
116
117 template<template<typename> typename wrapper>
118 void
test05()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 int
main()127 main()
128 {
129 test01();
130 test02();
131 test03();
132 test04();
133 test05<forward_iterator_wrapper>();
134 test05<random_access_iterator_wrapper>();
135 }
136