1 // Demonstrate and test boost/operators.hpp on std::iterators --------------//
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)
8 // See http://www.boost.org for most recent version including documentation.
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)
15 #define BOOST_INCLUDE_MAIN
16 #include <boost/test/test_tools.hpp> // for main
18 #include <boost/config.hpp> // for BOOST_STATIC_CONSTANT
19 #include <boost/cstdlib.hpp> // for boost::exit_success
20 #include <boost/operators.hpp> // for boost::random_access_iterator_helper
22 #include <cstddef> // for std::ptrdiff_t, std::size_t
23 #include <cstring> // for std::strcmp
24 #include <iostream> // for std::cout (std::endl, ends, and flush indirectly)
25 #include <string> // for std::string
26 #include <sstream> // for std::stringstream
28 # ifdef BOOST_NO_STDC_NAMESPACE
29 namespace std
{ using ::strcmp
; }
33 // Iterator test class
34 template <class T
, class R
, class P
>
36 : public boost::random_access_iterator_helper
<
37 test_iter
<T
,R
,P
>, T
, std::ptrdiff_t, P
, R
>
39 typedef test_iter self
;
41 typedef std::ptrdiff_t Distance
;
44 explicit test_iter(T
* i
=0) : _i(i
) { }
45 test_iter(const self
& x
) : _i(x
._i
) { }
46 self
& operator=(const self
& x
) { _i
= x
._i
; return *this; }
47 Reference
operator*() const { return *_i
; }
48 self
& operator++() { ++_i
; return *this; }
49 self
& operator--() { --_i
; return *this; }
50 self
& operator+=(Distance n
) { _i
+= n
; return *this; }
51 self
& operator-=(Distance n
) { _i
-= n
; return *this; }
52 bool operator==(const self
& x
) const { return _i
== x
._i
; }
53 bool operator<(const self
& x
) const { return _i
< x
._i
; }
54 friend Distance
operator-(const self
& x
, const self
& y
) {
61 // Iterator operator testing classes
65 // Test data and types
66 BOOST_STATIC_CONSTANT( std::size_t, fruit_length
= 6u );
68 typedef std::string fruit_array_type
[ fruit_length
];
70 static fruit_array_type fruit
;
74 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
75 // A definition is required even for integral static constants
76 const std::size_t test_opr_base::fruit_length
;
79 template <typename T
, typename R
= T
&, typename P
= T
*>
81 : public test_opr_base
83 typedef test_opr
<T
, R
, P
> self_type
;
91 typedef test_iter
<T
, R
, P
> iter_type
;
94 static void master_test( char const name
[] );
98 static iter_type
const fruit_begin
;
99 static iter_type
const fruit_end
;
102 static void post_increment_test();
103 static void post_decrement_test();
104 static void indirect_referral_test();
105 static void offset_addition_test();
106 static void reverse_offset_addition_test();
107 static void offset_subtraction_test();
108 static void comparison_test();
109 static void indexing_test();
114 // Class-static data definitions
115 test_opr_base::fruit_array_type
116 test_opr_base::fruit
= { "apple", "orange", "pear", "peach", "grape", "plum" };
118 template <typename T
, typename R
, typename P
>
119 typename test_opr
<T
, R
, P
>::iter_type
const
120 test_opr
<T
, R
, P
>::fruit_begin
= test_iter
<T
,R
,P
>( fruit
);
122 template <typename T
, typename R
, typename P
>
123 typename test_opr
<T
, R
, P
>::iter_type
const
124 test_opr
<T
, R
, P
>::fruit_end
= test_iter
<T
,R
,P
>( fruit
+ fruit_length
);
127 // Main testing function
129 test_main( int , char * [] )
133 typedef test_opr
<string
, string
&, string
*> test1_type
;
134 typedef test_opr
<string
, string
const &, string
const *> test2_type
;
136 test1_type::master_test( "non-const string" );
137 test2_type::master_test( "const string" );
139 return boost::exit_success
;
142 // Tests for all of the operators added by random_access_iterator_helper
143 template <typename T
, typename R
, typename P
>
145 test_opr
<T
, R
, P
>::master_test
150 std::cout
<< "Doing test run for " << name
<< '.' << std::endl
;
152 post_increment_test();
153 post_decrement_test();
154 indirect_referral_test();
155 offset_addition_test();
156 reverse_offset_addition_test();
157 offset_subtraction_test();
162 // Test post-increment
163 template <typename T
, typename R
, typename P
>
165 test_opr
<T
, R
, P
>::post_increment_test
169 std::cout
<< "\tDoing post-increment test." << std::endl
;
171 std::stringstream oss
;
172 for ( iter_type i
= fruit_begin
; i
!= fruit_end
; )
177 BOOST_CHECK( oss
.str() == "apple orange pear peach grape plum ");
180 // Test post-decrement
181 template <typename T
, typename R
, typename P
>
183 test_opr
<T
, R
, P
>::post_decrement_test
187 std::cout
<< "\tDoing post-decrement test." << std::endl
;
189 std::stringstream oss
;
190 for ( iter_type i
= fruit_end
; i
!= fruit_begin
; )
196 BOOST_CHECK( oss
.str() == "plum grape peach pear orange apple ");
199 // Test indirect structure referral
200 template <typename T
, typename R
, typename P
>
202 test_opr
<T
, R
, P
>::indirect_referral_test
206 std::cout
<< "\tDoing indirect reference test." << std::endl
;
208 std::stringstream oss
;
209 for ( iter_type i
= fruit_begin
; i
!= fruit_end
; ++i
)
211 oss
<< i
->size() << ' ';
214 BOOST_CHECK( oss
.str() == "5 6 4 5 5 4 ");
217 // Test offset addition
218 template <typename T
, typename R
, typename P
>
220 test_opr
<T
, R
, P
>::offset_addition_test
224 std::cout
<< "\tDoing offset addition test." << std::endl
;
226 std::ptrdiff_t const two
= 2;
227 std::stringstream oss
;
228 for ( iter_type i
= fruit_begin
; i
!= fruit_end
; i
= i
+ two
)
233 BOOST_CHECK( oss
.str() == "apple pear grape ");
236 // Test offset addition, in reverse order
237 template <typename T
, typename R
, typename P
>
239 test_opr
<T
, R
, P
>::reverse_offset_addition_test
243 std::cout
<< "\tDoing reverse offset addition test." << std::endl
;
245 std::ptrdiff_t const two
= 2;
246 std::stringstream oss
;
247 for ( iter_type i
= fruit_begin
; i
!= fruit_end
; i
= two
+ i
)
252 BOOST_CHECK( oss
.str() == "apple pear grape ");
255 // Test offset subtraction
256 template <typename T
, typename R
, typename P
>
258 test_opr
<T
, R
, P
>::offset_subtraction_test
262 std::cout
<< "\tDoing offset subtraction test." << std::endl
;
264 std::ptrdiff_t const two
= 2;
265 std::stringstream oss
;
266 for ( iter_type i
= fruit_end
; fruit_begin
< i
; )
269 if ( (fruit_begin
< i
) || (fruit_begin
== i
) )
275 BOOST_CHECK( oss
.str() == "grape pear apple ");
279 template <typename T
, typename R
, typename P
>
281 test_opr
<T
, R
, P
>::comparison_test
286 using std::ptrdiff_t;
288 cout
<< "\tDoing comparison tests.\n\t\tPass:";
290 for ( iter_type i
= fruit_begin
; i
!= fruit_end
; ++i
)
292 ptrdiff_t const i_offset
= i
- fruit_begin
;
294 cout
<< ' ' << *i
<< std::flush
;
295 for ( iter_type j
= fruit_begin
; j
!= fruit_end
; ++j
)
297 ptrdiff_t const j_offset
= j
- fruit_begin
;
299 BOOST_CHECK( (i
!= j
) == (i_offset
!= j_offset
) );
300 BOOST_CHECK( (i
> j
) == (i_offset
> j_offset
) );
301 BOOST_CHECK( (i
<= j
) == (i_offset
<= j_offset
) );
302 BOOST_CHECK( (i
>= j
) == (i_offset
>= j_offset
) );
309 template <typename T
, typename R
, typename P
>
311 test_opr
<T
, R
, P
>::indexing_test
315 std::cout
<< "\tDoing indexing test." << std::endl
;
317 std::stringstream oss
;
318 for ( std::size_t k
= 0u ; k
< fruit_length
; ++k
)
320 oss
<< fruit_begin
[ k
] << ' ';
323 BOOST_CHECK( oss
.str() == "apple orange pear peach grape plum ");