1// Boost.Range library
2//
3// Copyright Neil Groves 2009. Use, modification and
4// distribution is subject to the Boost Software License, Version
5// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7//
8//
9// For more information, see http://www.boost.org/libs/range/
10//
11#include <boost/range/adaptor/filtered.hpp>
12
13#include <boost/test/test_tools.hpp>
14#include <boost/test/unit_test.hpp>
15
16#include <boost/assign.hpp>
17#include <boost/range/algorithm_ext.hpp>
18
19#include <algorithm>
20#include <list>
21#include <set>
22#include <string>
23#include <vector>
24#include <sstream>
25
26namespace boost
27{
28 namespace
29 {
30 struct always_false_pred
31 {
32 template< class T1 >
33 bool operator()(T1) const { return false; }
34 };
35
36 struct always_true_pred
37 {
38 template< class T1 >
39 bool operator()(T1) const { return true; }
40 };
41
42 struct is_even
43 {
44 template< class IntegerT >
45 bool operator()( IntegerT x ) const { return x % 2 == 0; }
46 };
47
48 struct is_odd
49 {
50 template< class IntegerT >
51 bool operator()( IntegerT x ) const { return x % 2 != 0; }
52 };
53
54 struct lambda_init
55 {
56 };
57
58 struct lambda
59 {
60 lambda(const lambda_init& init) {}
61 lambda(const lambda& rhs) {}
62
63 template< class T1 >
64 bool operator()(T1) const { return false; }
65
66 private:
67 lambda() {}
68 lambda& operator=(const lambda& rhs) { return *this; }
69 };
70
71 template< class Container, class Pred >
72 void filtered_test_impl( Container& c, Pred pred )
73 {
74 using namespace boost::adaptors;
75
76 typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t;
77
78 // This is my preferred syntax using the | operator.
79 std::vector< value_t > test_result1;
80 boost::push_back(test_result1, c | filtered(pred));
81
82 // This is an alternative syntax preferred by some.
83 std::vector< value_t > test_result2;
84 boost::push_back(test_result2, adaptors::filter(c, pred));
85
86 // Calculate the reference result.
87 std::vector< value_t > reference_result;
88 typedef BOOST_DEDUCED_TYPENAME Container::const_iterator iter_t;
89 for (iter_t it = c.begin(); it != c.end(); ++it)
90 {
91 if (pred(*it))
92 reference_result.push_back(*it);
93 }
94
95 BOOST_CHECK_EQUAL_COLLECTIONS( reference_result.begin(),
96 reference_result.end(),
97 test_result1.begin(),
98 test_result1.end() );
99
100 BOOST_CHECK_EQUAL_COLLECTIONS( reference_result.begin(),
101 reference_result.end(),
102 test_result2.begin(),
103 test_result2.end() );
104 }
105
106 template< class Rng >
107 void check_copy_assign(Rng r)
108 {
109 Rng r2 = r;
110 r2 = r;
111 }
112
113 template< class Container, class Pred >
114 void filtered_range_copy_assign(Container& c, Pred pred)
115 {
116 using namespace boost::adaptors;
117 check_copy_assign(c | filtered(pred));
118 check_copy_assign(adaptors::filter(c, pred));
119 }
120
121 template< class Container, class Pred, class PredInit >
122 void filtered_test_impl()
123 {
124 using namespace boost::assign;
125
126 Container c;
127 PredInit init;
128 Pred pred(init);
129
130 // test empty container
131 filtered_test_impl(c, pred);
132
133 // test one element
134 c += 1;
135 filtered_test_impl(c, pred);
136
137 // test many elements
138 c += 1,2,2,2,3,4,4,4,4,5,6,7,8,9,9;
139 filtered_test_impl(c, pred);
140
141 // test the range and iterator are copy assignable
142 filtered_range_copy_assign(c, pred);
143 }
144
145 template< class Container >
146 void filtered_test_all_predicates()
147 {
148 filtered_test_impl< Container, always_false_pred, always_false_pred >();
149 filtered_test_impl< Container, always_true_pred, always_true_pred >();
150 filtered_test_impl< Container, is_odd, is_odd >();
151 filtered_test_impl< Container, is_even, is_even >();
152 filtered_test_impl< Container, lambda, lambda_init >();
153 }
154
155 void ticket_10988_single_pass()
156 {
157 std::vector<int> v;
158 std::string str("0 1 2 3 4 5");
159 std::istringstream in(str);
160
161 boost::push_back(on&: v,
162 from: boost::make_iterator_range(
163 Begin: std::istream_iterator<int>(in),
164 End: std::istream_iterator<int>())
165 | boost::adaptors::filtered(is_even()));
166
167 std::vector<int> reference;
168 for (int i = 0; i < 6; i += 2)
169 {
170 reference.push_back(x: i);
171 }
172 BOOST_CHECK_EQUAL_COLLECTIONS(
173 reference.begin(), reference.end(),
174 v.begin(), v.end());
175 }
176
177 void filtered_test()
178 {
179 filtered_test_all_predicates< std::vector< int > >();
180 filtered_test_all_predicates< std::list< int > >();
181 filtered_test_all_predicates< std::set< int > >();
182 filtered_test_all_predicates< std::multiset< int > >();
183 ticket_10988_single_pass();
184 }
185 }
186}
187
188boost::unit_test::test_suite*
189init_unit_test_suite(int argc, char* argv[])
190{
191 boost::unit_test::test_suite* test
192 = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.filtered" );
193
194 test->add( BOOST_TEST_CASE( &boost::filtered_test ) );
195
196 return test;
197}
198

source code of boost/libs/range/test/adaptor_test/filtered.cpp