diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp index e906539..18223d0 100644 --- a/include/boost/operators.hpp +++ b/include/boost/operators.hpp @@ -9,6 +9,11 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker) +// 27 Aug 01 'left' form for non commutative operators added; +// additional classes for groups of related operators added; +// workaround for empty base class optimization +// bug of GCC 3.0 (Helmut Zeisel) // 25 Jun 01 output_iterator_helper changes: removed default template // parameters, added support for self-proxying, additional // documentation and tests (Aleksey Gurtovoy) @@ -81,7 +86,14 @@ namespace boost { namespace detail { +// Helmut Zeisel, empty base class optimization bug with GCC 3.0.0 +#if defined(__GNUCC__) && __GNUC__==3 && __GNUC_MINOR__==0 && __GNU_PATCHLEVEL__==0 +class empty_base { + bool dummy; +}; +#else class empty_base {}; +#endif } // namespace detail } // namespace boost @@ -168,6 +180,13 @@ struct subtractable2 : B friend T operator-(T x, const U& y) { return x -= y; } }; +template +struct subtractable2_left : B +{ + friend T operator-(const U& x, const T& y) + { T result(x); return result -= y; } +}; + template struct subtractable1 : B { @@ -180,6 +199,13 @@ struct dividable2 : B friend T operator/(T x, const U& y) { return x /= y; } }; +template +struct dividable2_left : B +{ + friend T operator/(const U& x, const T& y) + { T result(x); return result /= y; } +}; + template struct dividable1 : B { @@ -192,6 +218,13 @@ struct modable2 : B friend T operator%(T x, const U& y) { return x %= y; } }; +template +struct modable2_left : B +{ + friend T operator%(const U& x, const T& y) + { T result(x); return result %= y; } +}; + template struct modable1 : B { @@ -463,12 +496,121 @@ struct shiftable1 , right_shiftable1 > {}; +template +struct ring_operators2 + : additive2 > > {}; + +template +struct ring_operators1 + : additive1 > {}; + +template +struct ordered_ring_operators2 + : ring_operators2 > {}; + +template +struct ordered_ring_operators1 + : ring_operators1 > {}; + +template +struct field_operators2 + : ring_operators2 > > {}; + +template +struct field_operators1 + : ring_operators1 > {}; + +template +struct ordered_field_operators2 + : field_operators2 > {}; + +template +struct ordered_field_operators1 + : field_operators1 > {}; + +template +struct euclidian_ring_operators2 + : ring_operators2 > > > > {}; + +template +struct euclidian_ring_operators1 + : ring_operators1 > > {}; + +template +struct ordered_euclidian_ring_operators2 + : totally_ordered2 > {}; + +template +struct ordered_euclidian_ring_operators1 + : totally_ordered1 > {}; + +template +struct input_iteratable + : equality_comparable1 > > {}; + +template +struct output_iteratable + : incrementable {}; + +template +struct forward_iteratable + : input_iteratable {}; + +template +struct bidirectional_iteratable + : forward_iteratable > {}; + +template +struct random_access_iteratable + : bidirectional_iteratable > > > {}; + #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE } // namespace boost #endif // BOOST_NO_OPERATORS_IN_NAMESPACE -// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE3 - +// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 - // // When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an // operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used @@ -479,6 +621,7 @@ struct shiftable1 #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE // The template is already in boost so we have nothing to do. +# define BOOST_IMPORT_TEMPLATE4(template_name) # define BOOST_IMPORT_TEMPLATE3(template_name) # define BOOST_IMPORT_TEMPLATE2(template_name) # define BOOST_IMPORT_TEMPLATE1(template_name) @@ -489,6 +632,7 @@ struct shiftable1 // Bring the names in with a using-declaration // to avoid stressing the compiler. +# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name; # define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name; # define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name; # define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name; @@ -497,6 +641,10 @@ struct shiftable1 // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration // from working, we are forced to use inheritance for that compiler. +# define BOOST_IMPORT_TEMPLATE4(template_name) \ + template \ + struct template_name : ::template_name {}; + # define BOOST_IMPORT_TEMPLATE3(template_name) \ template \ struct template_name : ::template_name {}; @@ -542,6 +690,15 @@ template struct is_chained_base { } // namespace boost +// Import a 4-type-argument operator template into boost (if neccessary) and +// provide a specialization of 'is_chained_base<>' for it. +# define BOOST_OPERATOR_TEMPLATE4(template_name4) \ + BOOST_IMPORT_TEMPLATE4(template_name4) \ + template \ + struct is_chained_base< ::boost::template_name4 > { \ + typedef ::boost::detail::true_t value; \ + }; + // Import a 3-type-argument operator template into boost (if neccessary) and // provide a specialization of 'is_chained_base<>' for it. # define BOOST_OPERATOR_TEMPLATE3(template_name3) \ @@ -610,6 +767,8 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1) #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# define BOOST_OPERATOR_TEMPLATE4(template_name4) \ + BOOST_IMPORT_TEMPLATE4(template_name4) # define BOOST_OPERATOR_TEMPLATE3(template_name3) \ BOOST_IMPORT_TEMPLATE3(template_name3) # define BOOST_OPERATOR_TEMPLATE2(template_name2) \ @@ -632,8 +791,11 @@ BOOST_OPERATOR_TEMPLATE(equality_comparable) BOOST_OPERATOR_TEMPLATE(multipliable) BOOST_OPERATOR_TEMPLATE(addable) BOOST_OPERATOR_TEMPLATE(subtractable) +BOOST_OPERATOR_TEMPLATE2(subtractable2_left) BOOST_OPERATOR_TEMPLATE(dividable) +BOOST_OPERATOR_TEMPLATE2(dividable2_left) BOOST_OPERATOR_TEMPLATE(modable) +BOOST_OPERATOR_TEMPLATE2(modable2_left) BOOST_OPERATOR_TEMPLATE(xorable) BOOST_OPERATOR_TEMPLATE(andable) BOOST_OPERATOR_TEMPLATE(orable) @@ -658,14 +820,27 @@ BOOST_OPERATOR_TEMPLATE(integer_arithmetic) BOOST_OPERATOR_TEMPLATE(bitwise) BOOST_OPERATOR_TEMPLATE1(unit_steppable) BOOST_OPERATOR_TEMPLATE(shiftable) +BOOST_OPERATOR_TEMPLATE(ring_operators) +BOOST_OPERATOR_TEMPLATE(ordered_ring_operators) +BOOST_OPERATOR_TEMPLATE(field_operators) +BOOST_OPERATOR_TEMPLATE(ordered_field_operators) +BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators) +BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators) +BOOST_OPERATOR_TEMPLATE2(input_iteratable) +BOOST_OPERATOR_TEMPLATE1(output_iteratable) +BOOST_OPERATOR_TEMPLATE2(forward_iteratable) +BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable) +BOOST_OPERATOR_TEMPLATE4(random_access_iteratable) #undef BOOST_OPERATOR_TEMPLATE +#undef BOOST_OPERATOR_TEMPLATE4 #undef BOOST_OPERATOR_TEMPLATE3 #undef BOOST_OPERATOR_TEMPLATE2 #undef BOOST_OPERATOR_TEMPLATE1 #undef BOOST_IMPORT_TEMPLATE1 #undef BOOST_IMPORT_TEMPLATE2 #undef BOOST_IMPORT_TEMPLATE3 +#undef BOOST_IMPORT_TEMPLATE4 // The following 'operators' classes can only be used portably if the derived class // declares ALL of the required member operators. @@ -699,20 +874,18 @@ template struct input_iterator_helper - : equality_comparable1 > > > {}; + > > {}; -template +template struct output_iterator_helper - : boost::incrementable > { - Derived& operator*() { return static_cast(*this); } - Derived& operator++() { return static_cast(*this); } + T& operator*() { return static_cast(*this); } + T& operator++() { return static_cast(*this); } }; template struct forward_iterator_helper - : equality_comparable1 > > > {}; + > > {}; template struct bidirectional_iterator_helper - : equality_comparable1 > > > {}; + > > {}; template struct random_access_iterator_helper - : totally_ordered1 > > > > > + > > { friend D requires_difference_operator(const T& x, const T& y) { return x - y; diff --git a/operators.htm b/operators.htm index 18434d9..11699d9 100644 --- a/operators.htm +++ b/operators.htm @@ -30,7 +30,11 @@ provided by the class.

  • Usage
      -
    • Two-Argument Template Forms
    • +
    • Two-Argument Template Forms +
    • Base Class Chaining and Object Size
    • Separate, Explicit Instantiation
    • @@ -39,7 +43,10 @@ provided by the class.

    • Example
    • Arithmetic operators + + ring_operators<T>
      + ring_operators1<T> + + + + ring_operators<T, U>
      + ring_operators2<T, U> + + + + ordered_ring_operators<T>
      + ordered_ring_operators1<T> + + + + ordered_ring_operators<T, U>
      + ordered_ring_operators2<T, U> + + + + field_operators<T>
      + field_operators1<T> + + + + field_operators<T, U>
      + field_operators2<T, U> + + + + ordered_field_operators<T>
      + ordered_field_operators1<T> + + + + ordered_field_operators<T, U>
      + ordered_field_operators2<T, U> + + + + euclidian_ring_operators<T>
      + euclidian_ring_operators1<T> + + + + euclidian_ring_operators<T, U>
      + euclidian_ring_operators2<T, U> + + + + ordered_euclidian_ring_operators<T>
      + ordered_euclidian_ring_operators1<T> + + + + ordered_euclidian_ring_operators<T, U>
      + ordered_euclidian_ring_operators2<T, U> + + +

      Example Templates

      @@ -888,19 +1063,87 @@ href="#chaining">base class chaining.

      -

      Iterator Helpers

      +

      Grouped Iterator Operators

      -

      There are five separate iterator helper classes, each for a -different category of iterator. Here is a summary of the core set of -operators that the custom iterator must define, and the extra operators -that are created by the helper classes. These classes cannot be used for base class chaining. For convenience, the helper -classes also fill in all of the typedef's required of iterators by the -C++ standard (iterator_category, value_type, -etc.).

      +

      There are five iterator operator class templates, each for a different +category of iterator. The following table shows the operator groups +for any category that a custom iterator could define. These class +templates have an additional optional template parameter B, +which is not shown, to support base class chaining.

      - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Iterator Helper Template ClassesIterator Operator Class Templates
      + + + + + + + + + + + + + +
      Key
      T: operand typeP: pointer type
      D: difference_typeR: reference type
      V: value_type
      TemplateComponent Operator Templates
      input_iteratable<T, P>
      output_iteratable<T>
      forward_iteratable<T, P>
      bidirectional_iteratable<T, P>
      random_access_iteratable<T, P, D, R>
      + +

      Iterator Helpers

      + +

      There are also five iterator helper class templates, each corresponding +to a different iterator category. These classes cannot be used for base class chaining. The following summaries +show that these class templates supply both the iterator operators from +the iterator operator class templates and +the iterator typedef's required by the C++ standard (iterator_category, +value_type, etc.).

      + + +
      Iterator Helper Class Templates
      @@ -926,16 +1169,14 @@ C++ standard (iterator_category, value_type, @@ -944,33 +1185,21 @@ C++ standard (iterator_category, value_type,
      Key
      input_iterator_helper<T, V, D, P, R> Supports the operations and has the requirements of
      output_iterator_helper<T> Supports the operations and has the requirements of See also [1], [2]. forward_iterator_helper<T, V, D, P, R> Supports the operations and has the requirements of
      bidirectional_iterator_helper<T, V, D, P, R> Supports the operations and has the requirements of
      random_access_iterator_helper<T, V, D, P, R> Supports the operations and has the requirements of To satisfy RandomAccessIterator, x1 - x2 with return convertible to D @@ -978,7 +1207,7 @@ C++ standard (iterator_category, value_type,
      -

      Iterator Helper Notes

      +

      Iterator Helper Notes

      [1] Unlike other iterator helpers templates, output_iterator_helper takes only one template parameter - the type of @@ -987,8 +1216,8 @@ restriction, the standard requires difference_type and value_type of any output iterator to be void (24.3.1 [lib.iterator.traits]), and output_iterator_helper template respects this -requirement. Also, output iterators in the standard have void pointer and -reference types, so the output_iterator_helper does the +requirement. Also, output iterators in the standard have void pointer and +reference types, so the output_iterator_helper does the same.

      [2] As self-proxying is the easiest and most common way to @@ -1008,13 +1237,13 @@ template<class UnaryFunction> struct function_output_iterator : boost::output_iterator_helper< function_output_iterator<UnaryFunction> > { - explicit function_output_iterator(UnaryFunction const& f = UnaryFunction()) + explicit function_output_iterator(UnaryFunction const& f = UnaryFunction()) : func(f) {} template<typename T> - function_output_iterator& operator=(T const& value) + function_output_iterator& operator=(T const& value) { - this->func(value); + this->func(value); return *this; } @@ -1093,6 +1322,10 @@ the test results with selected platforms.

      partial ordering, and arithmetic conversions. Added the grouped operator classes. Added helper classes for input and output iterators. + +
      Helmut Zeisel +
      Contributed the 'left' operators and added some + grouped operator classes.

      Note for Users of Older Versions

      @@ -1142,7 +1375,7 @@ the library remain backward-compatible.


      -

      Revised: 25 Jun 2001

      +

      Revised: 30 Oct 2001

      Copyright © David Abrahams and Beman Dawes 1999-2001. Permission to copy, use, modify, sell and distribute this document is diff --git a/operators_test.cpp b/operators_test.cpp index ce03e87..ac7988d 100644 --- a/operators_test.cpp +++ b/operators_test.cpp @@ -8,6 +8,8 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 01 Oct 01 Added tests for "left" operators +// and new grouped operators. (Helmut Zeisel) // 20 May 01 Output progress messages. Added tests for new operator // templates. Updated random number generator. Changed tests to // use Boost Test Tools library. (Daryle Walker) @@ -184,6 +186,74 @@ namespace template T true_value(Wrapped4 x) { return x.value(); } + // U must be convertible to T + template + class Wrapped5 + : boost::ordered_field_operators2, U> + , boost::ordered_field_operators1 > + { + public: + explicit Wrapped5( T v = T() ) : _value(v) {} + + // Conversion from U to Wrapped5 + Wrapped5(U u) : _value(u) {} + + T value() const { return _value; } + bool operator<(const Wrapped5& x) const { return _value < x._value; } + bool operator<(U u) const { return _value < u; } + bool operator>(U u) const { return _value > u; } + bool operator==(const Wrapped5& u) const { return _value == u._value; } + bool operator==(U u) const { return _value == u; } + Wrapped5& operator/=(const Wrapped5& u) { _value /= u._value; return *this;} + Wrapped5& operator/=(U u) { _value /= u; return *this;} + Wrapped5& operator*=(const Wrapped5& u) { _value *= u._value; return *this;} + Wrapped5& operator*=(U u) { _value *= u; return *this;} + Wrapped5& operator-=(const Wrapped5& u) { _value -= u._value; return *this;} + Wrapped5& operator-=(U u) { _value -= u; return *this;} + Wrapped5& operator+=(const Wrapped5& u) { _value += u._value; return *this;} + Wrapped5& operator+=(U u) { _value += u; return *this;} + + private: + T _value; + }; + template + T true_value(Wrapped5 x) { return x.value(); } + + // U must be convertible to T + template + class Wrapped6 + : boost::ordered_euclidian_ring_operators2, U> + , boost::ordered_euclidian_ring_operators1 > + { + public: + explicit Wrapped6( T v = T() ) : _value(v) {} + + // Conversion from U to Wrapped6 + Wrapped6(U u) : _value(u) {} + + T value() const { return _value; } + bool operator<(const Wrapped6& x) const { return _value < x._value; } + bool operator<(U u) const { return _value < u; } + bool operator>(U u) const { return _value > u; } + bool operator==(const Wrapped6& u) const { return _value == u._value; } + bool operator==(U u) const { return _value == u; } + Wrapped6& operator%=(const Wrapped6& u) { _value %= u._value; return *this;} + Wrapped6& operator%=(U u) { _value %= u; return *this;} + Wrapped6& operator/=(const Wrapped6& u) { _value /= u._value; return *this;} + Wrapped6& operator/=(U u) { _value /= u; return *this;} + Wrapped6& operator*=(const Wrapped6& u) { _value *= u._value; return *this;} + Wrapped6& operator*=(U u) { _value *= u; return *this;} + Wrapped6& operator-=(const Wrapped6& u) { _value -= u._value; return *this;} + Wrapped6& operator-=(U u) { _value -= u; return *this;} + Wrapped6& operator+=(const Wrapped6& u) { _value += u._value; return *this;} + Wrapped6& operator+=(U u) { _value += u; return *this;} + + private: + T _value; + }; + template + T true_value(Wrapped6 x) { return x.value(); } + // MyInt uses only the single template-argument form of all_operators<> typedef Wrapped1 MyInt; @@ -193,6 +263,10 @@ namespace typedef Wrapped4 MyShort; + typedef Wrapped5 MyDoubleInt; + + typedef Wrapped6 MyLongInt; + template void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -267,6 +341,13 @@ namespace BOOST_TEST( (x1 - y1).value() == (x2 - y2) ); } + template + void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + BOOST_TEST( (y1 - x1).value() == (y2 - x2) ); + } + template void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -275,6 +356,14 @@ namespace BOOST_TEST( (x1 / y1).value() == (x2 / y2) ); } + template + void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + if ( x2 != 0 ) + BOOST_TEST( (y1 / x1).value() == (y2 / x2) ); + } + template void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -283,6 +372,14 @@ namespace BOOST_TEST( (x1 % y1).value() == (x2 % y2) ); } + template + void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + if ( x2 != 0 ) + BOOST_TEST( (y1 % x1).value() == (y2 % x2) ); + } + template void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) { @@ -374,6 +471,14 @@ namespace test_decrementable( x1, x2 ); } + template + void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + test_subtractable_left( x1, y1, x2, y2 ); + test_dividable_left( x1, y1, x2, y2 ); + test_modable_left( x1, y1, x2, y2 ); + } + template struct tester { @@ -388,6 +493,19 @@ namespace } }; + template + struct tester_left + { + void operator()(boost::minstd_rand& randomizer) const + { + Big b1 = Big( randomizer() ); + Big b2 = Big( randomizer() ); + Small s = Small( randomizer() ); + + test_left( Wrapped6(b1), s, b1, s ); + } + }; + // added as a regression test. We had a bug which this uncovered. struct Point : boost::addable; template Wrapped2; template Wrapped2; template Wrapped2; + +template Wrapped6; +template Wrapped6; +template Wrapped6; +template Wrapped6; +template Wrapped6; +template Wrapped6; #endif #define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) ) @@ -459,6 +584,14 @@ test_main( int , char * [] ) tester()(r); tester()(r); tester()(r); + + tester_left()(r); + tester_left()(r); + tester_left()(r); + + tester_left()(r); + tester_left()(r); + tester_left()(r); } cout << "Did random tester loop." << endl; @@ -653,5 +786,106 @@ test_main( int , char * [] ) cout << "Performed tests on MyShort objects.\n"; + MyDoubleInt di1(1); + MyDoubleInt di2(2.); + MyDoubleInt half(0.5); + MyDoubleInt di; + MyDoubleInt tmp; + + BOOST_TEST( di1.value() == 1 ); + BOOST_TEST( di2.value() == 2 ); + BOOST_TEST( di2.value() == 2 ); + BOOST_TEST( di.value() == 0 ); + + cout << "Created MyDoubleInt objects.\n"; + + PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) ); + + BOOST_TEST( di2 == di ); + BOOST_TEST( 2 == di ); + BOOST_TEST( di == 2 ); + BOOST_TEST( di1 < di2 ); + BOOST_TEST( 1 < di2 ); + BOOST_TEST( di1 <= di2 ); + BOOST_TEST( 1 <= di2 ); + BOOST_TEST( di2 > di1 ); + BOOST_TEST( di2 > 1 ); + BOOST_TEST( di2 >= di1 ); + BOOST_TEST( di2 >= 1 ); + BOOST_TEST( di1 / di2 == half ); + BOOST_TEST( di1 / 2 == half ); + BOOST_TEST( 1 / di2 == half ); + PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=2) == half) ); + PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=di2) == half) ); + BOOST_TEST( di1 * di2 == di2 ); + BOOST_TEST( di1 * 2 == di2 ); + BOOST_TEST( 1 * di2 == di2 ); + PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=2) == di2) ); + PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=di2) == di2) ); + BOOST_TEST( di2 - di1 == di1 ); + BOOST_TEST( di2 - 1 == di1 ); + BOOST_TEST( 2 - di1 == di1 ); + PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=1) == di1) ); + PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=di1) == di1) ); + BOOST_TEST( di1 + di1 == di2 ); + BOOST_TEST( di1 + 1 == di2 ); + BOOST_TEST( 1 + di1 == di2 ); + PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=1) == di2) ); + PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=di1) == di2) ); + + cout << "Performed tests on MyDoubleInt objects.\n"; + + MyLongInt li1(1); + MyLongInt li2(2); + MyLongInt li; + MyLongInt tmp2; + + BOOST_TEST( li1.value() == 1 ); + BOOST_TEST( li2.value() == 2 ); + BOOST_TEST( li.value() == 0 ); + + cout << "Created MyLongInt objects.\n"; + + PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) ); + + BOOST_TEST( li2 == li ); + BOOST_TEST( 2 == li ); + BOOST_TEST( li == 2 ); + BOOST_TEST( li1 < li2 ); + BOOST_TEST( 1 < li2 ); + BOOST_TEST( li1 <= li2 ); + BOOST_TEST( 1 <= li2 ); + BOOST_TEST( li2 > li1 ); + BOOST_TEST( li2 > 1 ); + BOOST_TEST( li2 >= li1 ); + BOOST_TEST( li2 >= 1 ); + BOOST_TEST( li1 % li2 == li1 ); + BOOST_TEST( li1 % 2 == li1 ); + BOOST_TEST( 1 % li2 == li1 ); + PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=2) == li1) ); + PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=li2) == li1) ); + BOOST_TEST( li1 / li2 == 0 ); + BOOST_TEST( li1 / 2 == 0 ); + BOOST_TEST( 1 / li2 == 0 ); + PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=2) == 0) ); + PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=li2) == 0) ); + BOOST_TEST( li1 * li2 == li2 ); + BOOST_TEST( li1 * 2 == li2 ); + BOOST_TEST( 1 * li2 == li2 ); + PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=2) == li2) ); + PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=li2) == li2) ); + BOOST_TEST( li2 - li1 == li1 ); + BOOST_TEST( li2 - 1 == li1 ); + BOOST_TEST( 2 - li1 == li1 ); + PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=1) == li1) ); + PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=li1) == li1) ); + BOOST_TEST( li1 + li1 == li2 ); + BOOST_TEST( li1 + 1 == li2 ); + BOOST_TEST( 1 + li1 == li2 ); + PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=1) == li2) ); + PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=li1) == li2) ); + + cout << "Performed tests on MyLongInt objects.\n"; + return boost::exit_success; }