• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  Demonstrate and test boost/operators.hpp on std::iterators  --------------//
2 
3 //  (C) Copyright Jeremy Siek 1999.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 
8 //  See http://www.boost.org for most recent version including documentation.
9 
10 //  Revision History
11 //  29 May 01 Factored implementation, added comparison tests, use Test Tools
12 //            library (Daryle Walker)
13 //  12 Dec 99 Initial version with iterator operators (Jeremy Siek)
14 
15 #include <boost/core/lightweight_test.hpp>
16 
17 #include <boost/config.hpp>     // for BOOST_STATIC_CONSTANT
18 #include <boost/operators.hpp>  // for boost::random_access_iterator_helper
19 
20 #include <cstddef>    // for std::ptrdiff_t, std::size_t
21 #include <cstring>    // for std::strcmp
22 #include <iostream>   // for std::cout (std::endl, ends, and flush indirectly)
23 #include <string>     // for std::string
24 #include <sstream>    // for std::stringstream
25 
26 # ifdef BOOST_NO_STDC_NAMESPACE
27     namespace std { using ::strcmp; }
28 # endif
29 
30 
31 // Iterator test class
32 template <class T, class R, class P>
33 struct test_iter
34   : public boost::random_access_iterator_helper<
35      test_iter<T,R,P>, T, std::ptrdiff_t, P, R>
36 {
37   typedef test_iter self;
38   typedef R Reference;
39   typedef std::ptrdiff_t Distance;
40 
41 public:
test_itertest_iter42   explicit test_iter(T* i =0) : _i(i) { }
test_itertest_iter43   test_iter(const self& x) : _i(x._i) { }
operator =test_iter44   self& operator=(const self& x) { _i = x._i; return *this; }
operator *test_iter45   Reference operator*() const { return *_i; }
operator ++test_iter46   self& operator++() { ++_i; return *this; }
operator --test_iter47   self& operator--() { --_i; return *this; }
operator +=test_iter48   self& operator+=(Distance n) { _i += n; return *this; }
operator -=test_iter49   self& operator-=(Distance n) { _i -= n; return *this; }
operator ==test_iter50   bool operator==(const self& x) const { return _i == x._i; }
operator <test_iter51   bool operator<(const self& x) const { return _i < x._i; }
operator -(const self & x,const self & y)52   friend Distance operator-(const self& x, const self& y) {
53     return x._i - y._i;
54   }
55 protected:
56   P _i;
57 };
58 
59 // Iterator operator testing classes
60 class test_opr_base
61 {
62 protected:
63     // Test data and types
64     BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u );
65 
66     typedef std::string  fruit_array_type[ fruit_length ];
67 
68     static  fruit_array_type    fruit;
69 
70 };  // test_opr_base
71 
72 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
73 //  A definition is required even for integral static constants
74 const std::size_t test_opr_base::fruit_length;
75 #endif
76 
77 template <typename T, typename R = T&, typename P = T*>
78 class test_opr
79     : public test_opr_base
80 {
81     typedef test_opr<T, R, P>  self_type;
82 
83 public:
84     // Types
85     typedef T  value_type;
86     typedef R  reference;
87     typedef P  pointer;
88 
89     typedef test_iter<T, R, P>  iter_type;
90 
91     // Test controller
92     static  void  master_test( char const name[] );
93 
94 private:
95     // Test data
96     static iter_type const  fruit_begin;
97     static iter_type const  fruit_end;
98 
99     // Test parts
100     static  void  post_increment_test();
101     static  void  post_decrement_test();
102     static  void  indirect_referral_test();
103     static  void  offset_addition_test();
104     static  void  reverse_offset_addition_test();
105     static  void  offset_subtraction_test();
106     static  void  comparison_test();
107     static  void  indexing_test();
108 
109 };  // test_opr
110 
111 
112 // Class-static data definitions
113 test_opr_base::fruit_array_type
114  test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" };
115 
116 template <typename T, typename R, typename P>
117   typename test_opr<T, R, P>::iter_type const
118  test_opr<T, R, P>::fruit_begin = test_iter<T,R,P>( fruit );
119 
120 template <typename T, typename R, typename P>
121 typename test_opr<T, R, P>::iter_type const
122  test_opr<T, R, P>::fruit_end = test_iter<T,R,P>( fruit + fruit_length );
123 
124 
125 // Main testing function
126 int
main()127 main()
128 {
129     using std::string;
130 
131     typedef test_opr<string, string &, string *>              test1_type;
132     typedef test_opr<string, string const &, string const *>  test2_type;
133 
134     test1_type::master_test( "non-const string" );
135     test2_type::master_test( "const string" );
136 
137     return boost::report_errors();
138 }
139 
140 // Tests for all of the operators added by random_access_iterator_helper
141 template <typename T, typename R, typename P>
142 void
master_test(char const name[])143 test_opr<T, R, P>::master_test
144 (
145     char const  name[]
146 )
147 {
148     std::cout << "Doing test run for " << name << '.' << std::endl;
149 
150     post_increment_test();
151     post_decrement_test();
152     indirect_referral_test();
153     offset_addition_test();
154     reverse_offset_addition_test();
155     offset_subtraction_test();
156     comparison_test();
157     indexing_test();
158 }
159 
160 // Test post-increment
161 template <typename T, typename R, typename P>
162 void
post_increment_test()163 test_opr<T, R, P>::post_increment_test
164 (
165 )
166 {
167     std::cout << "\tDoing post-increment test." << std::endl;
168 
169     std::stringstream oss;
170     for ( iter_type i = fruit_begin ; i != fruit_end ; )
171     {
172         oss << *i++ << ' ';
173     }
174 
175     BOOST_TEST( oss.str() == "apple orange pear peach grape plum ");
176 }
177 
178 // Test post-decrement
179 template <typename T, typename R, typename P>
180 void
post_decrement_test()181 test_opr<T, R, P>::post_decrement_test
182 (
183 )
184 {
185     std::cout << "\tDoing post-decrement test." << std::endl;
186 
187     std::stringstream oss;
188     for ( iter_type i = fruit_end ; i != fruit_begin ; )
189     {
190         i--;
191         oss << *i << ' ';
192     }
193 
194     BOOST_TEST( oss.str() == "plum grape peach pear orange apple ");
195 }
196 
197 // Test indirect structure referral
198 template <typename T, typename R, typename P>
199 void
indirect_referral_test()200 test_opr<T, R, P>::indirect_referral_test
201 (
202 )
203 {
204     std::cout << "\tDoing indirect reference test." << std::endl;
205 
206     std::stringstream oss;
207     for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
208     {
209         oss << i->size() << ' ';
210     }
211 
212     BOOST_TEST( oss.str() == "5 6 4 5 5 4 ");
213 }
214 
215 // Test offset addition
216 template <typename T, typename R, typename P>
217 void
offset_addition_test()218 test_opr<T, R, P>::offset_addition_test
219 (
220 )
221 {
222     std::cout << "\tDoing offset addition test." << std::endl;
223 
224     std::ptrdiff_t const  two = 2;
225     std::stringstream oss;
226     for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two )
227     {
228         oss << *i << ' ';
229     }
230 
231     BOOST_TEST( oss.str() == "apple pear grape ");
232 }
233 
234 // Test offset addition, in reverse order
235 template <typename T, typename R, typename P>
236 void
reverse_offset_addition_test()237 test_opr<T, R, P>::reverse_offset_addition_test
238 (
239 )
240 {
241     std::cout << "\tDoing reverse offset addition test." << std::endl;
242 
243     std::ptrdiff_t const  two = 2;
244     std::stringstream oss;
245     for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i )
246     {
247         oss << *i << ' ';
248     }
249 
250     BOOST_TEST( oss.str() == "apple pear grape ");
251 }
252 
253 // Test offset subtraction
254 template <typename T, typename R, typename P>
255 void
offset_subtraction_test()256 test_opr<T, R, P>::offset_subtraction_test
257 (
258 )
259 {
260     std::cout << "\tDoing offset subtraction test." << std::endl;
261 
262     std::ptrdiff_t const  two = 2;
263     std::stringstream oss;
264     for ( iter_type i = fruit_end ; fruit_begin < i ; )
265     {
266         i = i - two;
267         if ( (fruit_begin < i) || (fruit_begin == i) )
268         {
269             oss << *i << ' ';
270         }
271     }
272 
273     BOOST_TEST( oss.str() == "grape pear apple ");
274 }
275 
276 // Test comparisons
277 template <typename T, typename R, typename P>
278 void
comparison_test()279 test_opr<T, R, P>::comparison_test
280 (
281 )
282 {
283     using std::cout;
284     using std::ptrdiff_t;
285 
286     cout << "\tDoing comparison tests.\n\t\tPass:";
287 
288     for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
289     {
290         ptrdiff_t const  i_offset = i - fruit_begin;
291 
292         cout << ' ' << *i << std::flush;
293         for ( iter_type j = fruit_begin ; j != fruit_end ; ++j )
294         {
295             ptrdiff_t const  j_offset = j - fruit_begin;
296 
297             BOOST_TEST( (i != j) == (i_offset != j_offset) );
298             BOOST_TEST( (i > j) == (i_offset > j_offset) );
299             BOOST_TEST( (i <= j) == (i_offset <= j_offset) );
300             BOOST_TEST( (i >= j) == (i_offset >= j_offset) );
301         }
302     }
303     cout << std::endl;
304 }
305 
306 // Test indexing
307 template <typename T, typename R, typename P>
308 void
indexing_test()309 test_opr<T, R, P>::indexing_test
310 (
311 )
312 {
313     std::cout << "\tDoing indexing test." << std::endl;
314 
315     std::stringstream oss;
316     for ( std::size_t k = 0u ; k < fruit_length ; ++k )
317     {
318         oss << fruit_begin[ k ] << ' ';
319     }
320 
321     BOOST_TEST( oss.str() == "apple orange pear peach grape plum ");
322 }
323