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
21template< class T >
22struct less_than
23{
24 T val;
25
26 less_than() : val(0)
27 {}
28
29 less_than( T t ) : val(t)
30 {}
31
32 bool operator()( const T& r ) const
33 {
34 return r < val;
35 }
36};
37
38
39
40template< class T >
41struct multiply
42{
43 T val;
44
45 typedef T& result_type;
46
47 multiply( T t ) : val(t)
48 { }
49
50 T& operator()( T& r ) const
51 {
52 return r *= 2;
53 }
54};
55
56
57
58template< class Rng >
59void 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
70template< class Rng >
71void check_direct()
72{
73 using namespace boost::adaptors;
74
75 Rng rng = boost::assign::list_of(t: 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(t: 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
106template< class IndirectRng >
107void 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
133template< class RandomAccessRng >
134void 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
157template< class Map >
158void check_map()
159{
160 using namespace boost::adaptors;
161
162 Map m;
163 m.insert( std::make_pair(x: 1,y: 2) );
164 m.insert( std::make_pair(x: 2,y: 2) );
165 m.insert( std::make_pair(x: 3,y: 2) );
166 m.insert( std::make_pair(x: 4,y: 2) );
167 m.insert( std::make_pair(x: 5,y: 2) );
168 m.insert( std::make_pair(x: 6,y: 2) );
169 m.insert( std::make_pair(x: 7,y: 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
179void 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> >( r: s | tokenized( "\\s+", -1 ) );
185}
186
187
188void 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( r: vec | adjacent_filtered( std::equal_to<int>() ) );
205 // check_copy( vec | indexed );
206 check_copy( r: vec | reversed );
207 check_copy( r: vec | uniqued );
208 check_copy( r: 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( r: map | map_values );
217 check_copy( r: map | map_keys );
218 check_copy( r: std::string( "a string" ) | tokenized( "\\s+", -1 ) );
219 check_copy( r: vec | filtered( less_than<int>(2) ) );
220 check_copy( r: vec | transformed( multiply<int>(2) ) );
221}
222
223using boost::unit_test::test_suite;
224
225test_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

source code of boost/libs/range/test/adaptors.cpp