1 // Boost.Range library
2 //
3 // Copyright Thorsten Ottosen 2006. 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 // For more information, see http://www.boost.org/libs/range/
9 //
10
11 #include <boost/range/adaptors.hpp>
12 #include <boost/test/test_tools.hpp>
13 #include <boost/test/unit_test.hpp>
14 #include <boost/foreach.hpp>
15 #include <boost/assign/list_of.hpp>
16 #include <vector>
17 #include <list>
18 #include <string>
19 #include <map>
20
21 template< class T >
22 struct less_than
23 {
24 T val;
25
less_thanless_than26 less_than() : val(0)
27 {}
28
less_thanless_than29 less_than( T t ) : val(t)
30 {}
31
operator ()less_than32 bool operator()( const T& r ) const
33 {
34 return r < val;
35 }
36 };
37
38
39
40 template< class T >
41 struct multiply
42 {
43 T val;
44
45 typedef T& result_type;
46
multiplymultiply47 multiply( T t ) : val(t)
48 { }
49
operator ()multiply50 T& operator()( T& r ) const
51 {
52 return r *= 2;
53 }
54 };
55
56
57
58 template< class Rng >
check_copy(Rng r)59 void check_copy( Rng r )
60 {
61 //
62 // Make sure the generated iterators
63 // can actually be copied
64 //
65 Rng r2 = r;
66 r2 = r;
67 }
68
69
70 template< class Rng >
check_direct()71 void check_direct()
72 {
73 using namespace boost::adaptors;
74
75 Rng rng = boost::assign::list_of(1)(2)(3)(4)(5).to_container( rng );
76 Rng out;
77
78 //
79 // test each alphabetically
80 //
81 BOOST_FOREACH( int i, rng | filtered( less_than<int>(4) )
82 /*| reversed*/
83 | transformed( multiply<int>(2) ) )
84 {
85 out.push_back( i );
86 }
87
88 BOOST_CHECK_EQUAL( out.size(), 3u );
89 BOOST_CHECK_EQUAL( *out.begin(), 2 );
90 BOOST_CHECK_EQUAL( *boost::next(out.begin()), 4 );
91 BOOST_CHECK_EQUAL( *boost::next(out.begin(),2), 6 );
92
93 rng = boost::assign::list_of(1)(1)(2)(2)(3)(3)(4)(5).to_container( rng );
94 out.clear();
95 /*
96 BOOST_FOREACH( int i, rng | adjacent_filtered( std::equal_to<int>() )
97 | uniqued )
98 {
99
100 out.push_back( i );
101 }*/
102
103 }
104
105
106 template< class IndirectRng >
check_indirect()107 void check_indirect()
108 {
109 using namespace boost::adaptors;
110
111 IndirectRng rng;
112
113 std::vector< boost::shared_ptr< int > > holder;
114
115 for( unsigned i = 0u; i != 20u; ++i )
116 {
117 boost::shared_ptr<int> v(new int(i));
118 rng.push_back( v.get() );
119 }
120
121 BOOST_FOREACH( int& i, rng | indirected | reversed
122 | transformed( multiply<int>(2) ) )
123 {
124 i += 1;
125 }
126
127
128
129 }
130
131
132
133 template< class RandomAccessRng >
check_random_access()134 void check_random_access()
135 {
136 using namespace boost::adaptors;
137
138 RandomAccessRng rng(1, 20u);
139 RandomAccessRng out;
140
141 BOOST_FOREACH( int i, rng | reversed
142 | transformed( multiply<int>(2) )
143 /* | sliced(0,15) */ )
144 {
145 out.push_back( i );
146 }
147
148
149 BOOST_FOREACH( int i, rng | copied(3u,13u) )
150 {
151 out.push_back( i );
152 }
153 }
154
155
156
157 template< class Map >
check_map()158 void check_map()
159 {
160 using namespace boost::adaptors;
161
162 Map m;
163 m.insert( std::make_pair(1,2) );
164 m.insert( std::make_pair(2,2) );
165 m.insert( std::make_pair(3,2) );
166 m.insert( std::make_pair(4,2) );
167 m.insert( std::make_pair(5,2) );
168 m.insert( std::make_pair(6,2) );
169 m.insert( std::make_pair(7,2) );
170
171 std::vector<int> keys
172 = boost::copy_range< std::vector<int> >( m | map_keys );
173 std::vector<int> values
174 = boost::copy_range< std::vector<int> >( m | map_values );
175 }
176
177
178
check_regex()179 void check_regex()
180 {
181 using namespace boost::adaptors;
182 std::string s("This is a string of tokens");
183 std::vector<std::string> tokens =
184 boost::copy_range< std::vector<std::string> >( s | tokenized( "\\s+", -1 ) );
185 }
186
187
check_adaptors()188 void check_adaptors()
189 {
190 check_direct< std::vector<int> >();
191 check_direct< std::list<int> >();
192 check_indirect< std::vector<int*> >();
193 check_indirect< std::list<int*> >();
194
195 check_map< std::map<int,int> >();
196 // check_random_access< std::vector<int> >();
197 check_regex();
198
199 using namespace boost::adaptors;
200 std::vector<int> vec(10u,20);
201 std::vector<int*> pvec;
202 std::map<int,int> map;
203
204 check_copy( vec | adjacent_filtered( std::equal_to<int>() ) );
205 // check_copy( vec | indexed );
206 check_copy( vec | reversed );
207 check_copy( vec | uniqued );
208 check_copy( pvec | indirected );
209
210 // check_copy( vec | sliced(1,5) );
211 //
212 // This does not return an iterator_range<>, so
213 // won't pass this test of implicit conversion
214 // check_copy( vec | copied(1,5) );
215 //
216 check_copy( map | map_values );
217 check_copy( map | map_keys );
218 check_copy( std::string( "a string" ) | tokenized( "\\s+", -1 ) );
219 check_copy( vec | filtered( less_than<int>(2) ) );
220 check_copy( vec | transformed( multiply<int>(2) ) );
221 }
222
223 using boost::unit_test::test_suite;
224
init_unit_test_suite(int argc,char * argv[])225 test_suite* init_unit_test_suite( int argc, char* argv[] )
226 {
227 using namespace boost;
228
229 test_suite* test = BOOST_TEST_SUITE( "Range Test Suite - Adaptors" );
230
231 test->add( BOOST_TEST_CASE( &check_adaptors ) );
232
233 return test;
234 }
235
236
237