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