• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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