1 // Demonstrate and test boost/operators.hpp -------------------------------//
2
3 // Copyright Beman Dawes 1999. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 // See http://www.boost.org/libs/utility for documentation.
8
9 // Revision History
10 // 03 Apr 08 Added convertible_to_bool (Daniel Frey)
11 // 01 Oct 01 Added tests for "left" operators
12 // and new grouped operators. (Helmut Zeisel)
13 // 20 May 01 Output progress messages. Added tests for new operator
14 // templates. Updated random number generator. Changed tests to
15 // use Boost Test Tools library. (Daryle Walker)
16 // 04 Jun 00 Added regression test for a bug I found (David Abrahams)
17 // 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
18 // ?? ??? 00 Major update to randomly test all one- and two- argument forms by
19 // wrapping integral types and comparing the results of operations
20 // to the results for the raw types (David Abrahams)
21 // 12 Dec 99 Minor update, output confirmation message.
22 // 15 Nov 99 Initial version
23
24 #include <boost/config.hpp> // for BOOST_MSVC
25 #include <boost/operators.hpp> // for the tested items
26 #include <boost/utility/detail/minstd_rand.hpp> // for boost::detail::minstd_rand
27 #include <boost/core/lightweight_test.hpp>
28
29 #include <iostream> // for std::cout (std::endl indirectly)
30
31
32 namespace
33 {
34 // avoiding a template version of true_value so as to not confuse VC++
true_value(int x)35 int true_value(int x) { return x; }
true_value(long x)36 long true_value(long x) { return x; }
true_value(signed char x)37 signed char true_value(signed char x) { return x; }
true_value(unsigned int x)38 unsigned int true_value(unsigned int x) { return x; }
true_value(unsigned long x)39 unsigned long true_value(unsigned long x) { return x; }
true_value(unsigned char x)40 unsigned char true_value(unsigned char x) { return x; }
41
42 // verify the minimum requirements for some operators
43 class convertible_to_bool
44 {
45 private:
46 bool _value;
47
48 typedef bool convertible_to_bool::*unspecified_bool_type;
49
50 void operator!() const;
51
52 public:
convertible_to_bool(const bool value)53 convertible_to_bool( const bool value ) : _value( value ) {}
54
operator unspecified_bool_type() const55 operator unspecified_bool_type() const
56 { return _value ? &convertible_to_bool::_value : 0; }
57 };
58
59 // The use of operators<> here tended to obscure
60 // interactions with certain compiler bugs
61 template <class T>
62 class Wrapped1
63 : boost::operators<Wrapped1<T> >
64 , boost::shiftable<Wrapped1<T> >
65 {
66 public:
Wrapped1(T v=T ())67 explicit Wrapped1( T v = T() ) : _value(v) {}
value() const68 T value() const { return _value; }
69
operator <(const Wrapped1 & x) const70 convertible_to_bool operator<(const Wrapped1& x) const
71 { return _value < x._value; }
operator ==(const Wrapped1 & x) const72 convertible_to_bool operator==(const Wrapped1& x) const
73 { return _value == x._value; }
74
operator +=(const Wrapped1 & x)75 Wrapped1& operator+=(const Wrapped1& x)
76 { _value += x._value; return *this; }
operator -=(const Wrapped1 & x)77 Wrapped1& operator-=(const Wrapped1& x)
78 { _value -= x._value; return *this; }
operator *=(const Wrapped1 & x)79 Wrapped1& operator*=(const Wrapped1& x)
80 { _value *= x._value; return *this; }
operator /=(const Wrapped1 & x)81 Wrapped1& operator/=(const Wrapped1& x)
82 { _value /= x._value; return *this; }
operator %=(const Wrapped1 & x)83 Wrapped1& operator%=(const Wrapped1& x)
84 { _value %= x._value; return *this; }
operator |=(const Wrapped1 & x)85 Wrapped1& operator|=(const Wrapped1& x)
86 { _value |= x._value; return *this; }
operator &=(const Wrapped1 & x)87 Wrapped1& operator&=(const Wrapped1& x)
88 { _value &= x._value; return *this; }
operator ^=(const Wrapped1 & x)89 Wrapped1& operator^=(const Wrapped1& x)
90 { _value ^= x._value; return *this; }
operator <<=(const Wrapped1 & x)91 Wrapped1& operator<<=(const Wrapped1& x)
92 { _value <<= x._value; return *this; }
operator >>=(const Wrapped1 & x)93 Wrapped1& operator>>=(const Wrapped1& x)
94 { _value >>= x._value; return *this; }
operator ++()95 Wrapped1& operator++() { ++_value; return *this; }
operator --()96 Wrapped1& operator--() { --_value; return *this; }
97
98 private:
99 T _value;
100 };
101 template <class T>
true_value(Wrapped1<T> x)102 T true_value(Wrapped1<T> x) { return x.value(); }
103
104 template <class T, class U>
105 class Wrapped2
106 : boost::operators<Wrapped2<T, U> >
107 , boost::operators2<Wrapped2<T, U>, U>
108 , boost::shiftable1<Wrapped2<T, U>
109 , boost::shiftable2<Wrapped2<T, U>, U > >
110 {
111 public:
Wrapped2(T v=T ())112 explicit Wrapped2( T v = T() ) : _value(v) {}
value() const113 T value() const { return _value; }
114
operator <(const Wrapped2 & x) const115 convertible_to_bool operator<(const Wrapped2& x) const
116 { return _value < x._value; }
operator ==(const Wrapped2 & x) const117 convertible_to_bool operator==(const Wrapped2& x) const
118 { return _value == x._value; }
119
operator +=(const Wrapped2 & x)120 Wrapped2& operator+=(const Wrapped2& x)
121 { _value += x._value; return *this; }
operator -=(const Wrapped2 & x)122 Wrapped2& operator-=(const Wrapped2& x)
123 { _value -= x._value; return *this; }
operator *=(const Wrapped2 & x)124 Wrapped2& operator*=(const Wrapped2& x)
125 { _value *= x._value; return *this; }
operator /=(const Wrapped2 & x)126 Wrapped2& operator/=(const Wrapped2& x)
127 { _value /= x._value; return *this; }
operator %=(const Wrapped2 & x)128 Wrapped2& operator%=(const Wrapped2& x)
129 { _value %= x._value; return *this; }
operator |=(const Wrapped2 & x)130 Wrapped2& operator|=(const Wrapped2& x)
131 { _value |= x._value; return *this; }
operator &=(const Wrapped2 & x)132 Wrapped2& operator&=(const Wrapped2& x)
133 { _value &= x._value; return *this; }
operator ^=(const Wrapped2 & x)134 Wrapped2& operator^=(const Wrapped2& x)
135 { _value ^= x._value; return *this; }
operator <<=(const Wrapped2 & x)136 Wrapped2& operator<<=(const Wrapped2& x)
137 { _value <<= x._value; return *this; }
operator >>=(const Wrapped2 & x)138 Wrapped2& operator>>=(const Wrapped2& x)
139 { _value >>= x._value; return *this; }
operator ++()140 Wrapped2& operator++() { ++_value; return *this; }
operator --()141 Wrapped2& operator--() { --_value; return *this; }
142
operator <(U u) const143 convertible_to_bool operator<(U u) const
144 { return _value < u; }
operator >(U u) const145 convertible_to_bool operator>(U u) const
146 { return _value > u; }
operator ==(U u) const147 convertible_to_bool operator==(U u) const
148 { return _value == u; }
149
operator +=(U u)150 Wrapped2& operator+=(U u) { _value += u; return *this; }
operator -=(U u)151 Wrapped2& operator-=(U u) { _value -= u; return *this; }
operator *=(U u)152 Wrapped2& operator*=(U u) { _value *= u; return *this; }
operator /=(U u)153 Wrapped2& operator/=(U u) { _value /= u; return *this; }
operator %=(U u)154 Wrapped2& operator%=(U u) { _value %= u; return *this; }
operator |=(U u)155 Wrapped2& operator|=(U u) { _value |= u; return *this; }
operator &=(U u)156 Wrapped2& operator&=(U u) { _value &= u; return *this; }
operator ^=(U u)157 Wrapped2& operator^=(U u) { _value ^= u; return *this; }
operator <<=(U u)158 Wrapped2& operator<<=(U u) { _value <<= u; return *this; }
operator >>=(U u)159 Wrapped2& operator>>=(U u) { _value >>= u; return *this; }
160
161 private:
162 T _value;
163 };
164 template <class T, class U>
true_value(Wrapped2<T,U> x)165 T true_value(Wrapped2<T,U> x) { return x.value(); }
166
167 template <class T>
168 class Wrapped3
169 : boost::equivalent<Wrapped3<T> >
170 , boost::partially_ordered<Wrapped3<T> >
171 , boost::equality_comparable<Wrapped3<T> >
172 {
173 public:
Wrapped3(T v=T ())174 explicit Wrapped3( T v = T() ) : _value(v) {}
value() const175 T value() const { return _value; }
176
operator <(const Wrapped3 & x) const177 convertible_to_bool operator<(const Wrapped3& x) const
178 { return _value < x._value; }
179
180 private:
181 T _value;
182 };
183 template <class T>
true_value(Wrapped3<T> x)184 T true_value(Wrapped3<T> x) { return x.value(); }
185
186 template <class T, class U>
187 class Wrapped4
188 : boost::equality_comparable1<Wrapped4<T, U>
189 , boost::equivalent1<Wrapped4<T, U>
190 , boost::partially_ordered1<Wrapped4<T, U> > > >
191 , boost::partially_ordered2<Wrapped4<T, U>, U
192 , boost::equivalent2<Wrapped4<T, U>, U
193 , boost::equality_comparable2<Wrapped4<T, U>, U> > >
194 {
195 public:
Wrapped4(T v=T ())196 explicit Wrapped4( T v = T() ) : _value(v) {}
value() const197 T value() const { return _value; }
198
operator <(const Wrapped4 & x) const199 convertible_to_bool operator<(const Wrapped4& x) const
200 { return _value < x._value; }
201
operator <(U u) const202 convertible_to_bool operator<(U u) const
203 { return _value < u; }
operator >(U u) const204 convertible_to_bool operator>(U u) const
205 { return _value > u; }
206
207 private:
208 T _value;
209 };
210 template <class T, class U>
true_value(Wrapped4<T,U> x)211 T true_value(Wrapped4<T,U> x) { return x.value(); }
212
213 // U must be convertible to T
214 template <class T, class U>
215 class Wrapped5
216 : boost::ordered_field_operators2<Wrapped5<T, U>, U>
217 , boost::ordered_field_operators1<Wrapped5<T, U> >
218 {
219 public:
Wrapped5(T v=T ())220 explicit Wrapped5( T v = T() ) : _value(v) {}
221
222 // Conversion from U to Wrapped5<T,U>
Wrapped5(U u)223 Wrapped5(U u) : _value(u) {}
224
value() const225 T value() const { return _value; }
226
operator <(const Wrapped5 & x) const227 convertible_to_bool operator<(const Wrapped5& x) const
228 { return _value < x._value; }
operator <(U u) const229 convertible_to_bool operator<(U u) const
230 { return _value < u; }
operator >(U u) const231 convertible_to_bool operator>(U u) const
232 { return _value > u; }
operator ==(const Wrapped5 & u) const233 convertible_to_bool operator==(const Wrapped5& u) const
234 { return _value == u._value; }
operator ==(U u) const235 convertible_to_bool operator==(U u) const
236 { return _value == u; }
237
operator /=(const Wrapped5 & u)238 Wrapped5& operator/=(const Wrapped5& u) { _value /= u._value; return *this;}
operator /=(U u)239 Wrapped5& operator/=(U u) { _value /= u; return *this;}
operator *=(const Wrapped5 & u)240 Wrapped5& operator*=(const Wrapped5& u) { _value *= u._value; return *this;}
operator *=(U u)241 Wrapped5& operator*=(U u) { _value *= u; return *this;}
operator -=(const Wrapped5 & u)242 Wrapped5& operator-=(const Wrapped5& u) { _value -= u._value; return *this;}
operator -=(U u)243 Wrapped5& operator-=(U u) { _value -= u; return *this;}
operator +=(const Wrapped5 & u)244 Wrapped5& operator+=(const Wrapped5& u) { _value += u._value; return *this;}
operator +=(U u)245 Wrapped5& operator+=(U u) { _value += u; return *this;}
246
247 private:
248 T _value;
249 };
250 template <class T, class U>
true_value(Wrapped5<T,U> x)251 T true_value(Wrapped5<T,U> x) { return x.value(); }
252
253 // U must be convertible to T
254 template <class T, class U>
255 class Wrapped6
256 : boost::ordered_euclidean_ring_operators2<Wrapped6<T, U>, U>
257 , boost::ordered_euclidean_ring_operators1<Wrapped6<T, U> >
258 {
259 public:
Wrapped6(T v=T ())260 explicit Wrapped6( T v = T() ) : _value(v) {}
261
262 // Conversion from U to Wrapped6<T,U>
Wrapped6(U u)263 Wrapped6(U u) : _value(u) {}
264
value() const265 T value() const { return _value; }
266
operator <(const Wrapped6 & x) const267 convertible_to_bool operator<(const Wrapped6& x) const
268 { return _value < x._value; }
operator <(U u) const269 convertible_to_bool operator<(U u) const
270 { return _value < u; }
operator >(U u) const271 convertible_to_bool operator>(U u) const
272 { return _value > u; }
operator ==(const Wrapped6 & u) const273 convertible_to_bool operator==(const Wrapped6& u) const
274 { return _value == u._value; }
operator ==(U u) const275 convertible_to_bool operator==(U u) const
276 { return _value == u; }
277
operator %=(const Wrapped6 & u)278 Wrapped6& operator%=(const Wrapped6& u) { _value %= u._value; return *this;}
operator %=(U u)279 Wrapped6& operator%=(U u) { _value %= u; return *this;}
operator /=(const Wrapped6 & u)280 Wrapped6& operator/=(const Wrapped6& u) { _value /= u._value; return *this;}
operator /=(U u)281 Wrapped6& operator/=(U u) { _value /= u; return *this;}
operator *=(const Wrapped6 & u)282 Wrapped6& operator*=(const Wrapped6& u) { _value *= u._value; return *this;}
operator *=(U u)283 Wrapped6& operator*=(U u) { _value *= u; return *this;}
operator -=(const Wrapped6 & u)284 Wrapped6& operator-=(const Wrapped6& u) { _value -= u._value; return *this;}
operator -=(U u)285 Wrapped6& operator-=(U u) { _value -= u; return *this;}
operator +=(const Wrapped6 & u)286 Wrapped6& operator+=(const Wrapped6& u) { _value += u._value; return *this;}
operator +=(U u)287 Wrapped6& operator+=(U u) { _value += u; return *this;}
288
289 private:
290 T _value;
291 };
292 template <class T, class U>
true_value(Wrapped6<T,U> x)293 T true_value(Wrapped6<T,U> x) { return x.value(); }
294
295 // MyInt uses only the single template-argument form of all_operators<>
296 typedef Wrapped1<int> MyInt;
297
298 typedef Wrapped2<long, long> MyLong;
299
300 typedef Wrapped3<signed char> MyChar;
301
302 typedef Wrapped4<short, short> MyShort;
303
304 typedef Wrapped5<double, int> MyDoubleInt;
305
306 typedef Wrapped6<long, int> MyLongInt;
307
308 template <class X1, class Y1, class X2, class Y2>
sanity_check(X1 x1,Y1 y1,X2 x2,Y2 y2)309 void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
310 {
311 BOOST_TEST( true_value(y1) == true_value(y2) );
312 BOOST_TEST( true_value(x1) == true_value(x2) );
313 }
314
315 template <class X1, class Y1, class X2, class Y2>
test_less_than_comparable_aux(X1 x1,Y1 y1,X2 x2,Y2 y2)316 void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
317 {
318 BOOST_TEST( static_cast<bool>(x1 < y1) == static_cast<bool>(x2 < y2) );
319 BOOST_TEST( static_cast<bool>(x1 <= y1) == static_cast<bool>(x2 <= y2) );
320 BOOST_TEST( static_cast<bool>(x1 >= y1) == static_cast<bool>(x2 >= y2) );
321 BOOST_TEST( static_cast<bool>(x1 > y1) == static_cast<bool>(x2 > y2) );
322 }
323
324 template <class X1, class Y1, class X2, class Y2>
test_less_than_comparable(X1 x1,Y1 y1,X2 x2,Y2 y2)325 void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
326 {
327 sanity_check( x1, y1, x2, y2 );
328 test_less_than_comparable_aux( x1, y1, x2, y2 );
329 test_less_than_comparable_aux( y1, x1, y2, x2 );
330 }
331
332 template <class X1, class Y1, class X2, class Y2>
test_equality_comparable_aux(X1 x1,Y1 y1,X2 x2,Y2 y2)333 void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
334 {
335 BOOST_TEST( static_cast<bool>(x1 == y1) == static_cast<bool>(x2 == y2) );
336 BOOST_TEST( static_cast<bool>(x1 != y1) == static_cast<bool>(x2 != y2) );
337 }
338
339 template <class X1, class Y1, class X2, class Y2>
test_equality_comparable(X1 x1,Y1 y1,X2 x2,Y2 y2)340 void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
341 {
342 sanity_check( x1, y1, x2, y2 );
343 test_equality_comparable_aux( x1, y1, x2, y2 );
344 test_equality_comparable_aux( y1, x1, y2, x2 );
345 }
346
347 template <class X1, class Y1, class X2, class Y2>
test_multipliable_aux(X1 x1,Y1 y1,X2 x2,Y2 y2)348 void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
349 {
350 BOOST_TEST( (x1 * y1).value() == (x2 * y2) );
351 }
352
353 template <class X1, class Y1, class X2, class Y2>
test_multipliable(X1 x1,Y1 y1,X2 x2,Y2 y2)354 void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
355 {
356 sanity_check( x1, y1, x2, y2 );
357 test_multipliable_aux( x1, y1, x2, y2 );
358 test_multipliable_aux( y1, x1, y2, x2 );
359 }
360
361 template <class A, class B>
test_value_equality(A a,B b)362 void test_value_equality(A a, B b)
363 {
364 BOOST_TEST(a.value() == b);
365 }
366
367 #define TEST_OP_R(op) test_value_equality(x1 op y1, x2 op y2)
368 #define TEST_OP_L(op) test_value_equality(y1 op x1, y2 op x2)
369
370 template <class X1, class Y1, class X2, class Y2>
test_addable_aux(X1 x1,Y1 y1,X2 x2,Y2 y2)371 void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
372 {
373 TEST_OP_R(+);
374 }
375
376 template <class X1, class Y1, class X2, class Y2>
test_addable(X1 x1,Y1 y1,X2 x2,Y2 y2)377 void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
378 {
379 sanity_check( x1, y1, x2, y2 );
380 test_addable_aux( x1, y1, x2, y2 );
381 test_addable_aux( y1, x1, y2, x2 );
382 }
383
384 template <class X1, class Y1, class X2, class Y2>
test_subtractable(X1 x1,Y1 y1,X2 x2,Y2 y2)385 void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
386 {
387 sanity_check( x1, y1, x2, y2 );
388 TEST_OP_R(-);
389 }
390
391 template <class X1, class Y1, class X2, class Y2>
test_subtractable_left(X1 x1,Y1 y1,X2 x2,Y2 y2)392 void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
393 {
394 sanity_check( x1, y1, x2, y2 );
395 TEST_OP_L(-);
396 }
397
398 template <class X1, class Y1, class X2, class Y2>
test_dividable(X1 x1,Y1 y1,X2 x2,Y2 y2)399 void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
400 {
401 sanity_check( x1, y1, x2, y2 );
402 if ( y2 != 0 )
403 TEST_OP_R(/);
404 }
405
406 template <class X1, class Y1, class X2, class Y2>
test_dividable_left(X1 x1,Y1 y1,X2 x2,Y2 y2)407 void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
408 {
409 sanity_check( x1, y1, x2, y2 );
410 if ( x2 != 0 )
411 TEST_OP_L(/);
412 }
413
414 template <class X1, class Y1, class X2, class Y2>
test_modable(X1 x1,Y1 y1,X2 x2,Y2 y2)415 void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
416 {
417 sanity_check( x1, y1, x2, y2 );
418 if ( y2 != 0 )
419 TEST_OP_R(%);
420 }
421
422 template <class X1, class Y1, class X2, class Y2>
test_modable_left(X1 x1,Y1 y1,X2 x2,Y2 y2)423 void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
424 {
425 sanity_check( x1, y1, x2, y2 );
426 if ( x2 != 0 )
427 TEST_OP_L(%);
428 }
429
430 template <class X1, class Y1, class X2, class Y2>
test_xorable_aux(X1 x1,Y1 y1,X2 x2,Y2 y2)431 void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
432 {
433 TEST_OP_R(^);
434 }
435
436 template <class X1, class Y1, class X2, class Y2>
test_xorable(X1 x1,Y1 y1,X2 x2,Y2 y2)437 void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
438 {
439 sanity_check( x1, y1, x2, y2 );
440 test_xorable_aux( x1, y1, x2, y2 );
441 test_xorable_aux( y1, x1, y2, x2 );
442 }
443
444 template <class X1, class Y1, class X2, class Y2>
test_andable_aux(X1 x1,Y1 y1,X2 x2,Y2 y2)445 void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
446 {
447 TEST_OP_R(&);
448 }
449
450 template <class X1, class Y1, class X2, class Y2>
test_andable(X1 x1,Y1 y1,X2 x2,Y2 y2)451 void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
452 {
453 sanity_check( x1, y1, x2, y2 );
454 test_andable_aux( x1, y1, x2, y2 );
455 test_andable_aux( y1, x1, y2, x2 );
456 }
457
458 template <class X1, class Y1, class X2, class Y2>
test_orable_aux(X1 x1,Y1 y1,X2 x2,Y2 y2)459 void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
460 {
461 TEST_OP_R(|);
462 }
463
464 template <class X1, class Y1, class X2, class Y2>
test_orable(X1 x1,Y1 y1,X2 x2,Y2 y2)465 void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
466 {
467 sanity_check( x1, y1, x2, y2 );
468 test_orable_aux( x1, y1, x2, y2 );
469 test_orable_aux( y1, x1, y2, x2 );
470 }
471
472 template <class X1, class Y1, class X2, class Y2>
test_left_shiftable(X1 x1,Y1 y1,X2 x2,Y2 y2)473 void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
474 {
475 sanity_check( x1, y1, x2, y2 );
476 TEST_OP_R(<<);
477 }
478
479 template <class X1, class Y1, class X2, class Y2>
test_right_shiftable(X1 x1,Y1 y1,X2 x2,Y2 y2)480 void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
481 {
482 sanity_check( x1, y1, x2, y2 );
483 TEST_OP_R(>>);
484 }
485
486 template <class X1, class X2>
test_incrementable(X1 x1,X2 x2)487 void test_incrementable(X1 x1, X2 x2)
488 {
489 sanity_check( x1, x1, x2, x2 );
490 BOOST_TEST( (x1++).value() == x2++ );
491 BOOST_TEST( x1.value() == x2 );
492 }
493
494 template <class X1, class X2>
test_decrementable(X1 x1,X2 x2)495 void test_decrementable(X1 x1, X2 x2)
496 {
497 sanity_check( x1, x1, x2, x2 );
498 BOOST_TEST( (x1--).value() == x2-- );
499 BOOST_TEST( x1.value() == x2 );
500 }
501
502 template <class X1, class Y1, class X2, class Y2>
test_all(X1 x1,Y1 y1,X2 x2,Y2 y2)503 void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
504 {
505 test_less_than_comparable( x1, y1, x2, y2 );
506 test_equality_comparable( x1, y1, x2, y2 );
507 test_multipliable( x1, y1, x2, y2 );
508 test_addable( x1, y1, x2, y2 );
509 test_subtractable( x1, y1, x2, y2 );
510 test_dividable( x1, y1, x2, y2 );
511 test_modable( x1, y1, x2, y2 );
512 test_xorable( x1, y1, x2, y2 );
513 test_andable( x1, y1, x2, y2 );
514 test_orable( x1, y1, x2, y2 );
515 test_left_shiftable( x1, y1, x2, y2 );
516 test_right_shiftable( x1, y1, x2, y2 );
517 test_incrementable( x1, x2 );
518 test_decrementable( x1, x2 );
519 }
520
521 template <class X1, class Y1, class X2, class Y2>
test_left(X1 x1,Y1 y1,X2 x2,Y2 y2)522 void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
523 {
524 test_subtractable_left( x1, y1, x2, y2 );
525 test_dividable_left( x1, y1, x2, y2 );
526 test_modable_left( x1, y1, x2, y2 );
527 }
528
529 template <class Big, class Small>
530 struct tester
531 {
operator ()__anon637075940111::tester532 void operator()(boost::detail::minstd_rand& randomizer) const
533 {
534 Big b1 = Big( randomizer() );
535 Big b2 = Big( randomizer() );
536 Small s = Small( randomizer() );
537
538 test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 );
539 test_all( Wrapped2<Big, Small>(b1), s, b1, s );
540 }
541 };
542
543 template <class Big, class Small>
544 struct tester_left
545 {
operator ()__anon637075940111::tester_left546 void operator()(boost::detail::minstd_rand& randomizer) const
547 {
548 Big b1 = Big( randomizer() );
549 Small s = Small( randomizer() );
550
551 test_left( Wrapped6<Big, Small>(b1), s, b1, s );
552 }
553 };
554
555 // added as a regression test. We had a bug which this uncovered.
556 struct Point
557 : boost::addable<Point
558 , boost::subtractable<Point> >
559 {
Point__anon637075940111::Point560 Point( int h, int v ) : h(h), v(v) {}
Point__anon637075940111::Point561 Point() :h(0), v(0) {}
operator +=__anon637075940111::Point562 const Point& operator+=( const Point& rhs )
563 { h += rhs.h; v += rhs.v; return *this; }
operator -=__anon637075940111::Point564 const Point& operator-=( const Point& rhs )
565 { h -= rhs.h; v -= rhs.v; return *this; }
566
567 int h;
568 int v;
569 };
570
571 } // unnamed namespace
572
573
574 // workaround for MSVC bug; for some reasons the compiler doesn't instantiate
575 // inherited operator templates at the moment it must, so the following
576 // explicit instantiations force it to do that.
577
578 #if defined(BOOST_MSVC) && (_MSC_VER < 1300)
579 template Wrapped1<int>;
580 template Wrapped1<long>;
581 template Wrapped1<unsigned int>;
582 template Wrapped1<unsigned long>;
583
584 template Wrapped2<int, int>;
585 template Wrapped2<int, signed char>;
586 template Wrapped2<long, signed char>;
587 template Wrapped2<long, int>;
588 template Wrapped2<long, long>;
589 template Wrapped2<unsigned int, unsigned int>;
590 template Wrapped2<unsigned int, unsigned char>;
591 template Wrapped2<unsigned long, unsigned int>;
592 template Wrapped2<unsigned long, unsigned char>;
593 template Wrapped2<unsigned long, unsigned long>;
594
595 template Wrapped6<long, int>;
596 template Wrapped6<long, signed char>;
597 template Wrapped6<int, signed char>;
598 template Wrapped6<unsigned long, unsigned int>;
599 template Wrapped6<unsigned long, unsigned char>;
600 template Wrapped6<unsigned int, unsigned char>;
601 #endif
602
603 #define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
604
605 int
main()606 main()
607 {
608 using std::cout;
609 using std::endl;
610
611 // Regression test.
612 Point x;
613 x = x + Point(3, 4);
614 x = x - Point(3, 4);
615
616 cout << "Created point, and operated on it." << endl;
617
618 for (int n = 0; n < 1000; ++n) // was 10,000 but took too long (Beman)
619 {
620 boost::detail::minstd_rand r;
621 tester<long, int>()(r);
622 tester<long, signed char>()(r);
623 tester<long, long>()(r);
624 tester<int, int>()(r);
625 tester<int, signed char>()(r);
626
627 tester<unsigned long, unsigned int>()(r);
628 tester<unsigned long, unsigned char>()(r);
629 tester<unsigned long, unsigned long>()(r);
630 tester<unsigned int, unsigned int>()(r);
631 tester<unsigned int, unsigned char>()(r);
632
633 tester_left<long, int>()(r);
634 tester_left<long, signed char>()(r);
635 tester_left<int, signed char>()(r);
636
637 tester_left<unsigned long, unsigned int>()(r);
638 tester_left<unsigned long, unsigned char>()(r);
639 tester_left<unsigned int, unsigned char>()(r);
640 }
641
642 cout << "Did random tester loop." << endl;
643
644 MyInt i1(1);
645 MyInt i2(2);
646 MyInt i;
647
648 BOOST_TEST( i1.value() == 1 );
649 BOOST_TEST( i2.value() == 2 );
650 BOOST_TEST( i.value() == 0 );
651
652 cout << "Created MyInt objects.\n";
653
654 PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) );
655
656 BOOST_TEST( static_cast<bool>(i2 == i) );
657 BOOST_TEST( static_cast<bool>(i1 != i2) );
658 BOOST_TEST( static_cast<bool>(i1 < i2) );
659 BOOST_TEST( static_cast<bool>(i1 <= i2) );
660 BOOST_TEST( static_cast<bool>(i <= i2) );
661 BOOST_TEST( static_cast<bool>(i2 > i1) );
662 BOOST_TEST( static_cast<bool>(i2 >= i1) );
663 BOOST_TEST( static_cast<bool>(i2 >= i) );
664
665 PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) );
666 PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) );
667 PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) );
668 PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) );
669 PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) );
670 PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) );
671 PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) );
672 PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) );
673 PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) );
674 PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) );
675 PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) );
676 PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) );
677
678 PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) );
679 PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) );
680
681 cout << "Performed tests on MyInt objects.\n";
682
683 MyLong j1(1);
684 MyLong j2(2);
685 MyLong j;
686
687 BOOST_TEST( j1.value() == 1 );
688 BOOST_TEST( j2.value() == 2 );
689 BOOST_TEST( j.value() == 0 );
690
691 cout << "Created MyLong objects.\n";
692
693 PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) );
694
695 BOOST_TEST( static_cast<bool>(j2 == j) );
696 BOOST_TEST( static_cast<bool>(2 == j) );
697 BOOST_TEST( static_cast<bool>(j2 == 2) );
698 BOOST_TEST( static_cast<bool>(j == j2) );
699 BOOST_TEST( static_cast<bool>(j1 != j2) );
700 BOOST_TEST( static_cast<bool>(j1 != 2) );
701 BOOST_TEST( static_cast<bool>(1 != j2) );
702 BOOST_TEST( static_cast<bool>(j1 < j2) );
703 BOOST_TEST( static_cast<bool>(1 < j2) );
704 BOOST_TEST( static_cast<bool>(j1 < 2) );
705 BOOST_TEST( static_cast<bool>(j1 <= j2) );
706 BOOST_TEST( static_cast<bool>(1 <= j2) );
707 BOOST_TEST( static_cast<bool>(j1 <= j) );
708 BOOST_TEST( static_cast<bool>(j <= j2) );
709 BOOST_TEST( static_cast<bool>(2 <= j2) );
710 BOOST_TEST( static_cast<bool>(j <= 2) );
711 BOOST_TEST( static_cast<bool>(j2 > j1) );
712 BOOST_TEST( static_cast<bool>(2 > j1) );
713 BOOST_TEST( static_cast<bool>(j2 > 1) );
714 BOOST_TEST( static_cast<bool>(j2 >= j1) );
715 BOOST_TEST( static_cast<bool>(2 >= j1) );
716 BOOST_TEST( static_cast<bool>(j2 >= 1) );
717 BOOST_TEST( static_cast<bool>(j2 >= j) );
718 BOOST_TEST( static_cast<bool>(2 >= j) );
719 BOOST_TEST( static_cast<bool>(j2 >= 2) );
720
721 BOOST_TEST( static_cast<bool>((j1 + 2) == 3) );
722 BOOST_TEST( static_cast<bool>((1 + j2) == 3) );
723 PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) );
724
725 BOOST_TEST( static_cast<bool>((j + 2) == 5) );
726 BOOST_TEST( static_cast<bool>((3 + j2) == 5) );
727 PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
728
729 BOOST_TEST( static_cast<bool>((j - 1) == 4) );
730 PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
731
732 BOOST_TEST( static_cast<bool>((j * 2) == 8) );
733 BOOST_TEST( static_cast<bool>((4 * j2) == 8) );
734 PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
735
736 BOOST_TEST( static_cast<bool>((j / 2) == 4) );
737 PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) );
738
739 BOOST_TEST( static_cast<bool>((j % 3) == 1) );
740 PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) );
741
742 PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) );
743
744 BOOST_TEST( static_cast<bool>((1 | j2 | j) == 7) );
745 BOOST_TEST( static_cast<bool>((j1 | 2 | j) == 7) );
746 BOOST_TEST( static_cast<bool>((j1 | j2 | 4) == 7) );
747 PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) );
748
749 BOOST_TEST( static_cast<bool>((7 & j2) == 2) );
750 BOOST_TEST( static_cast<bool>((j & 2) == 2) );
751 PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) );
752
753 PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) );
754
755 BOOST_TEST( static_cast<bool>((3 ^ j1) == 2) );
756 BOOST_TEST( static_cast<bool>((j ^ 1) == 2) );
757 PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) );
758
759 PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) );
760
761 BOOST_TEST( static_cast<bool>((j1 << 2) == 4) );
762 BOOST_TEST( static_cast<bool>((j2 << 1) == 4) );
763 PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) );
764
765 BOOST_TEST( static_cast<bool>((j >> 2) == 1) );
766 BOOST_TEST( static_cast<bool>((j2 >> 1) == 1) );
767 PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) );
768
769 cout << "Performed tests on MyLong objects.\n";
770
771 MyChar k1(1);
772 MyChar k2(2);
773 MyChar k;
774
775 BOOST_TEST( k1.value() == 1 );
776 BOOST_TEST( k2.value() == 2 );
777 BOOST_TEST( k.value() == 0 );
778
779 cout << "Created MyChar objects.\n";
780
781 PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) );
782
783 BOOST_TEST( static_cast<bool>(k2 == k) );
784 BOOST_TEST( static_cast<bool>(k1 != k2) );
785 BOOST_TEST( static_cast<bool>(k1 < k2) );
786 BOOST_TEST( static_cast<bool>(k1 <= k2) );
787 BOOST_TEST( static_cast<bool>(k <= k2) );
788 BOOST_TEST( static_cast<bool>(k2 > k1) );
789 BOOST_TEST( static_cast<bool>(k2 >= k1) );
790 BOOST_TEST( static_cast<bool>(k2 >= k) );
791
792 cout << "Performed tests on MyChar objects.\n";
793
794 MyShort l1(1);
795 MyShort l2(2);
796 MyShort l;
797
798 BOOST_TEST( l1.value() == 1 );
799 BOOST_TEST( l2.value() == 2 );
800 BOOST_TEST( l.value() == 0 );
801
802 cout << "Created MyShort objects.\n";
803
804 PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) );
805
806 BOOST_TEST( static_cast<bool>(l2 == l) );
807 BOOST_TEST( static_cast<bool>(2 == l) );
808 BOOST_TEST( static_cast<bool>(l2 == 2) );
809 BOOST_TEST( static_cast<bool>(l == l2) );
810 BOOST_TEST( static_cast<bool>(l1 != l2) );
811 BOOST_TEST( static_cast<bool>(l1 != 2) );
812 BOOST_TEST( static_cast<bool>(1 != l2) );
813 BOOST_TEST( static_cast<bool>(l1 < l2) );
814 BOOST_TEST( static_cast<bool>(1 < l2) );
815 BOOST_TEST( static_cast<bool>(l1 < 2) );
816 BOOST_TEST( static_cast<bool>(l1 <= l2) );
817 BOOST_TEST( static_cast<bool>(1 <= l2) );
818 BOOST_TEST( static_cast<bool>(l1 <= l) );
819 BOOST_TEST( static_cast<bool>(l <= l2) );
820 BOOST_TEST( static_cast<bool>(2 <= l2) );
821 BOOST_TEST( static_cast<bool>(l <= 2) );
822 BOOST_TEST( static_cast<bool>(l2 > l1) );
823 BOOST_TEST( static_cast<bool>(2 > l1) );
824 BOOST_TEST( static_cast<bool>(l2 > 1) );
825 BOOST_TEST( static_cast<bool>(l2 >= l1) );
826 BOOST_TEST( static_cast<bool>(2 >= l1) );
827 BOOST_TEST( static_cast<bool>(l2 >= 1) );
828 BOOST_TEST( static_cast<bool>(l2 >= l) );
829 BOOST_TEST( static_cast<bool>(2 >= l) );
830 BOOST_TEST( static_cast<bool>(l2 >= 2) );
831
832 cout << "Performed tests on MyShort objects.\n";
833
834 MyDoubleInt di1(1);
835 MyDoubleInt di2(2.);
836 MyDoubleInt half(0.5);
837 MyDoubleInt di;
838 MyDoubleInt tmp;
839
840 BOOST_TEST( di1.value() == 1 );
841 BOOST_TEST( di2.value() == 2 );
842 BOOST_TEST( di2.value() == 2 );
843 BOOST_TEST( di.value() == 0 );
844
845 cout << "Created MyDoubleInt objects.\n";
846
847 PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) );
848
849 BOOST_TEST( static_cast<bool>(di2 == di) );
850 BOOST_TEST( static_cast<bool>(2 == di) );
851 BOOST_TEST( static_cast<bool>(di == 2) );
852 BOOST_TEST( static_cast<bool>(di1 < di2) );
853 BOOST_TEST( static_cast<bool>(1 < di2) );
854 BOOST_TEST( static_cast<bool>(di1 <= di2) );
855 BOOST_TEST( static_cast<bool>(1 <= di2) );
856 BOOST_TEST( static_cast<bool>(di2 > di1) );
857 BOOST_TEST( static_cast<bool>(di2 > 1) );
858 BOOST_TEST( static_cast<bool>(di2 >= di1) );
859 BOOST_TEST( static_cast<bool>(di2 >= 1) );
860 BOOST_TEST( static_cast<bool>(di1 / di2 == half) );
861 BOOST_TEST( static_cast<bool>(di1 / 2 == half) );
862 BOOST_TEST( static_cast<bool>(1 / di2 == half) );
863 PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp/=2) == half) );
864 PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp/=di2) == half) );
865 BOOST_TEST( static_cast<bool>(di1 * di2 == di2) );
866 BOOST_TEST( static_cast<bool>(di1 * 2 == di2) );
867 BOOST_TEST( static_cast<bool>(1 * di2 == di2) );
868 PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp*=2) == di2) );
869 PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp*=di2) == di2) );
870 BOOST_TEST( static_cast<bool>(di2 - di1 == di1) );
871 BOOST_TEST( static_cast<bool>(di2 - 1 == di1) );
872 BOOST_TEST( static_cast<bool>(2 - di1 == di1) );
873 PRIVATE_EXPR_TEST( (tmp=di2), static_cast<bool>((tmp-=1) == di1) );
874 PRIVATE_EXPR_TEST( (tmp=di2), static_cast<bool>((tmp-=di1) == di1) );
875 BOOST_TEST( static_cast<bool>(di1 + di1 == di2) );
876 BOOST_TEST( static_cast<bool>(di1 + 1 == di2) );
877 BOOST_TEST( static_cast<bool>(1 + di1 == di2) );
878 PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp+=1) == di2) );
879 PRIVATE_EXPR_TEST( (tmp=di1), static_cast<bool>((tmp+=di1) == di2) );
880
881 cout << "Performed tests on MyDoubleInt objects.\n";
882
883 MyLongInt li1(1);
884 MyLongInt li2(2);
885 MyLongInt li;
886 MyLongInt tmp2;
887
888 BOOST_TEST( li1.value() == 1 );
889 BOOST_TEST( li2.value() == 2 );
890 BOOST_TEST( li.value() == 0 );
891
892 cout << "Created MyLongInt objects.\n";
893
894 PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) );
895
896 BOOST_TEST( static_cast<bool>(li2 == li) );
897 BOOST_TEST( static_cast<bool>(2 == li) );
898 BOOST_TEST( static_cast<bool>(li == 2) );
899 BOOST_TEST( static_cast<bool>(li1 < li2) );
900 BOOST_TEST( static_cast<bool>(1 < li2) );
901 BOOST_TEST( static_cast<bool>(li1 <= li2) );
902 BOOST_TEST( static_cast<bool>(1 <= li2) );
903 BOOST_TEST( static_cast<bool>(li2 > li1) );
904 BOOST_TEST( static_cast<bool>(li2 > 1) );
905 BOOST_TEST( static_cast<bool>(li2 >= li1) );
906 BOOST_TEST( static_cast<bool>(li2 >= 1) );
907 BOOST_TEST( static_cast<bool>(li1 % li2 == li1) );
908 BOOST_TEST( static_cast<bool>(li1 % 2 == li1) );
909 BOOST_TEST( static_cast<bool>(1 % li2 == li1) );
910 PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2%=2) == li1) );
911 PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2%=li2) == li1) );
912 BOOST_TEST( static_cast<bool>(li1 / li2 == 0) );
913 BOOST_TEST( static_cast<bool>(li1 / 2 == 0) );
914 BOOST_TEST( static_cast<bool>(1 / li2 == 0) );
915 PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2/=2) == 0) );
916 PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2/=li2) == 0) );
917 BOOST_TEST( static_cast<bool>(li1 * li2 == li2) );
918 BOOST_TEST( static_cast<bool>(li1 * 2 == li2) );
919 BOOST_TEST( static_cast<bool>(1 * li2 == li2) );
920 PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2*=2) == li2) );
921 PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2*=li2) == li2) );
922 BOOST_TEST( static_cast<bool>(li2 - li1 == li1) );
923 BOOST_TEST( static_cast<bool>(li2 - 1 == li1) );
924 BOOST_TEST( static_cast<bool>(2 - li1 == li1) );
925 PRIVATE_EXPR_TEST( (tmp2=li2), static_cast<bool>((tmp2-=1) == li1) );
926 PRIVATE_EXPR_TEST( (tmp2=li2), static_cast<bool>((tmp2-=li1) == li1) );
927 BOOST_TEST( static_cast<bool>(li1 + li1 == li2) );
928 BOOST_TEST( static_cast<bool>(li1 + 1 == li2) );
929 BOOST_TEST( static_cast<bool>(1 + li1 == li2) );
930 PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2+=1) == li2) );
931 PRIVATE_EXPR_TEST( (tmp2=li1), static_cast<bool>((tmp2+=li1) == li2) );
932
933 cout << "Performed tests on MyLongInt objects.\n";
934
935 return boost::report_errors();
936 }
937