mirror of
https://github.com/boostorg/utility.git
synced 2025-05-09 15:04:00 +00:00
changes from Daryle Walker
[SVN r10264]
This commit is contained in:
parent
dd3cfe1837
commit
b7c8e0c17f
@ -1,20 +1,20 @@
|
|||||||
// Boost operators.hpp header file ----------------------------------------//
|
// Boost operators.hpp header file ----------------------------------------//
|
||||||
|
|
||||||
// (C) Copyright David Abrahams 1999. Permission to copy, use,
|
// (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001.
|
||||||
// modify, sell and distribute this software is granted provided this
|
// Permission to copy, use, modify, sell and distribute this software is
|
||||||
// copyright notice appears in all copies. This software is provided
|
// granted provided this copyright notice appears in all copies. This
|
||||||
// "as is" without express or implied warranty, and with no claim as
|
// software is provided "as is" without express or implied warranty, and
|
||||||
// to its suitability for any purpose.
|
// with no claim as to its suitability for any purpose.
|
||||||
|
|
||||||
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
|
||||||
// sell and distribute this software is granted provided this
|
|
||||||
// copyright notice appears in all copies. This software is provided
|
|
||||||
// "as is" without express or implied warranty, and with no claim as
|
|
||||||
// to its suitability for any purpose.
|
|
||||||
|
|
||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// Revision History
|
||||||
|
// 29 May 01 Added operator classes for << and >>. Added input and output
|
||||||
|
// iterator helper classes. Added classes to connect equality and
|
||||||
|
// relational operators. Added classes for groups of related
|
||||||
|
// operators. Reimplemented example operator and iterator helper
|
||||||
|
// classes in terms of the new groups. (Daryle Walker, with help
|
||||||
|
// from Alexy Gurtovoy)
|
||||||
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
|
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
|
||||||
// supplied arguments from actually being used (Dave Abrahams)
|
// supplied arguments from actually being used (Dave Abrahams)
|
||||||
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
||||||
@ -282,12 +282,190 @@ struct indexable : B
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// More operator classes (contributed by Daryle Walker) --------------------//
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct left_shiftable2 : B
|
||||||
|
{
|
||||||
|
friend T operator<<(T x, const U& y) { return x <<= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct left_shiftable1 : B
|
||||||
|
{
|
||||||
|
friend T operator<<(T x, const T& y) { return x <<= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct right_shiftable2 : B
|
||||||
|
{
|
||||||
|
friend T operator>>(T x, const U& y) { return x >>= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct right_shiftable1 : B
|
||||||
|
{
|
||||||
|
friend T operator>>(T x, const T& y) { return x >>= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct equivalent2 : B
|
||||||
|
{
|
||||||
|
friend bool operator==(const T& x, const U& y)
|
||||||
|
{
|
||||||
|
return !(x < y) && !(x > y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct equivalent1 : B
|
||||||
|
{
|
||||||
|
friend bool operator==(const T&x, const T&y)
|
||||||
|
{
|
||||||
|
return !(x < y) && !(y < x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct partially_ordered2 : B
|
||||||
|
{
|
||||||
|
friend bool operator<=(const T& x, const U& y)
|
||||||
|
{ return (x < y) || (x == y); }
|
||||||
|
friend bool operator>=(const T& x, const U& y)
|
||||||
|
{ return (x > y) || (x == y); }
|
||||||
|
friend bool operator>(const U& x, const T& y)
|
||||||
|
{ return y < x; }
|
||||||
|
friend bool operator<(const U& x, const T& y)
|
||||||
|
{ return y > x; }
|
||||||
|
friend bool operator<=(const U& x, const T& y)
|
||||||
|
{ return (y > x) || (y == x); }
|
||||||
|
friend bool operator>=(const U& x, const T& y)
|
||||||
|
{ return (y < x) || (y == x); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct partially_ordered1 : B
|
||||||
|
{
|
||||||
|
friend bool operator>(const T& x, const T& y)
|
||||||
|
{ return y < x; }
|
||||||
|
friend bool operator<=(const T& x, const T& y)
|
||||||
|
{ return (x < y) || (x == y); }
|
||||||
|
friend bool operator>=(const T& x, const T& y)
|
||||||
|
{ return (y < x) || (x == y); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Combined operator classes (contributed by Daryle Walker) ----------------//
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct totally_ordered2
|
||||||
|
: less_than_comparable2<T, U
|
||||||
|
, equality_comparable2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct totally_ordered1
|
||||||
|
: less_than_comparable1<T
|
||||||
|
, equality_comparable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct additive2
|
||||||
|
: addable2<T, U
|
||||||
|
, subtractable2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct additive1
|
||||||
|
: addable1<T
|
||||||
|
, subtractable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct multiplicative2
|
||||||
|
: multipliable2<T, U
|
||||||
|
, dividable2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct multiplicative1
|
||||||
|
: multipliable1<T
|
||||||
|
, dividable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct integer_multiplicative2
|
||||||
|
: multiplicative2<T, U
|
||||||
|
, modable2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct integer_multiplicative1
|
||||||
|
: multiplicative1<T
|
||||||
|
, modable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct arithmetic2
|
||||||
|
: additive2<T, U
|
||||||
|
, multiplicative2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct arithmetic1
|
||||||
|
: additive1<T
|
||||||
|
, multiplicative1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct integer_arithmetic2
|
||||||
|
: additive2<T, U
|
||||||
|
, integer_multiplicative2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct integer_arithmetic1
|
||||||
|
: additive1<T
|
||||||
|
, integer_multiplicative1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct bitwise2
|
||||||
|
: xorable2<T, U
|
||||||
|
, andable2<T, U
|
||||||
|
, orable2<T, U, B
|
||||||
|
> > > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct bitwise1
|
||||||
|
: xorable1<T
|
||||||
|
, andable1<T
|
||||||
|
, orable1<T, B
|
||||||
|
> > > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct unit_steppable
|
||||||
|
: incrementable<T
|
||||||
|
, decrementable<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct shiftable2
|
||||||
|
: left_shiftable2<T, U
|
||||||
|
, right_shiftable2<T, U, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct shiftable1
|
||||||
|
: left_shiftable1<T
|
||||||
|
, right_shiftable1<T, B
|
||||||
|
> > {};
|
||||||
|
|
||||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
// BOOST_IMPORT_TEMPLATE1/BOOST_IMPORT_TEMPLATE2 -
|
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE3 -
|
||||||
//
|
//
|
||||||
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
|
// 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
|
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
|
||||||
@ -295,12 +473,31 @@ struct indexable : B
|
|||||||
// two-argument forms. Note that these macros expect to be invoked from within
|
// two-argument forms. Note that these macros expect to be invoked from within
|
||||||
// boost.
|
// boost.
|
||||||
|
|
||||||
#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE)
|
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
# if defined(BOOST_NO_USING_TEMPLATE)
|
// The template is already in boost so we have nothing to do.
|
||||||
|
# define BOOST_IMPORT_TEMPLATE3(template_name)
|
||||||
|
# define BOOST_IMPORT_TEMPLATE2(template_name)
|
||||||
|
# define BOOST_IMPORT_TEMPLATE1(template_name)
|
||||||
|
|
||||||
|
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
|
# ifndef BOOST_NO_USING_TEMPLATE
|
||||||
|
|
||||||
|
// Bring the names in with a using-declaration
|
||||||
|
// to avoid stressing the compiler.
|
||||||
|
# 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;
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
// 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_TEMPLATE3(template_name) \
|
||||||
|
template <class T, class U, class V, class B = ::boost::detail::empty_base> \
|
||||||
|
struct template_name : ::template_name<T, U, V, B> {};
|
||||||
|
|
||||||
// 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_TEMPLATE2(template_name) \
|
# define BOOST_IMPORT_TEMPLATE2(template_name) \
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
struct template_name : ::template_name<T, U, B> {};
|
struct template_name : ::template_name<T, U, B> {};
|
||||||
@ -309,21 +506,8 @@ struct indexable : B
|
|||||||
template <class T, class B = ::boost::detail::empty_base> \
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
struct template_name : ::template_name<T, B> {};
|
struct template_name : ::template_name<T, B> {};
|
||||||
|
|
||||||
# else
|
|
||||||
|
|
||||||
// Otherwise, bring the names in with a using-declaration to avoid
|
|
||||||
// stressing the compiler
|
|
||||||
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
|
|
||||||
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
|
|
||||||
|
|
||||||
# endif // BOOST_NO_USING_TEMPLATE
|
# endif // BOOST_NO_USING_TEMPLATE
|
||||||
|
|
||||||
#else // !BOOST_NO_OPERATORS_IN_NAMESPACE
|
|
||||||
|
|
||||||
// The template is already in boost so we have nothing to do.
|
|
||||||
# define BOOST_IMPORT_TEMPLATE2(template_name)
|
|
||||||
# define BOOST_IMPORT_TEMPLATE1(template_name)
|
|
||||||
|
|
||||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -332,7 +516,7 @@ struct indexable : B
|
|||||||
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
||||||
// neccessary.
|
// neccessary.
|
||||||
//
|
//
|
||||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
// is_chained_base<> - a traits class used to distinguish whether an operator
|
// is_chained_base<> - a traits class used to distinguish whether an operator
|
||||||
// template argument is being used for base class chaining, or is specifying a
|
// template argument is being used for base class chaining, or is specifying a
|
||||||
@ -355,6 +539,15 @@ template<class T> struct is_chained_base {
|
|||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
|
// 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) \
|
||||||
|
BOOST_IMPORT_TEMPLATE3(template_name3) \
|
||||||
|
template<class T, class U, class V, class B> \
|
||||||
|
struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
|
||||||
|
typedef ::boost::detail::true_t value; \
|
||||||
|
};
|
||||||
|
|
||||||
// Import a 2-type-argument operator template into boost (if neccessary) and
|
// Import a 2-type-argument operator template into boost (if neccessary) and
|
||||||
// provide a specialization of 'is_chained_base<>' for it.
|
// provide a specialization of 'is_chained_base<>' for it.
|
||||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||||
@ -414,6 +607,8 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1)
|
|||||||
|
|
||||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
||||||
|
BOOST_IMPORT_TEMPLATE3(template_name3)
|
||||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||||
BOOST_IMPORT_TEMPLATE2(template_name2)
|
BOOST_IMPORT_TEMPLATE2(template_name2)
|
||||||
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
||||||
@ -442,47 +637,41 @@ BOOST_OPERATOR_TEMPLATE(orable)
|
|||||||
|
|
||||||
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
||||||
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
||||||
|
|
||||||
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
|
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE3(indexable)
|
||||||
|
|
||||||
// indexable doesn't follow the patterns above (it has 4 template arguments), so
|
BOOST_OPERATOR_TEMPLATE(left_shiftable)
|
||||||
// we just write out the compiler hacks explicitly.
|
BOOST_OPERATOR_TEMPLATE(right_shiftable)
|
||||||
#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
|
BOOST_OPERATOR_TEMPLATE(equivalent)
|
||||||
# ifdef BOOST_NO_USING_TEMPLATE
|
BOOST_OPERATOR_TEMPLATE(partially_ordered)
|
||||||
template <class T, class I, class R, class B = ::boost::detail::empty_base>
|
|
||||||
struct indexable : ::indexable<T,I,R,B> {};
|
|
||||||
# else
|
|
||||||
using ::indexable;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
BOOST_OPERATOR_TEMPLATE(totally_ordered)
|
||||||
template <class T, class I, class R, class B>
|
BOOST_OPERATOR_TEMPLATE(additive)
|
||||||
struct is_chained_base< ::boost::indexable<T, I, R, B> > {
|
BOOST_OPERATOR_TEMPLATE(multiplicative)
|
||||||
typedef ::boost::detail::true_t operator_template_type;
|
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
|
||||||
};
|
BOOST_OPERATOR_TEMPLATE(arithmetic)
|
||||||
#endif
|
BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(bitwise)
|
||||||
|
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE(shiftable)
|
||||||
|
|
||||||
#undef BOOST_OPERATOR_TEMPLATE
|
#undef BOOST_OPERATOR_TEMPLATE
|
||||||
|
#undef BOOST_OPERATOR_TEMPLATE3
|
||||||
#undef BOOST_OPERATOR_TEMPLATE2
|
#undef BOOST_OPERATOR_TEMPLATE2
|
||||||
#undef BOOST_OPERATOR_TEMPLATE1
|
#undef BOOST_OPERATOR_TEMPLATE1
|
||||||
#undef BOOST_IMPORT_TEMPLATE1
|
#undef BOOST_IMPORT_TEMPLATE1
|
||||||
#undef BOOST_IMPORT_TEMPLATE2
|
#undef BOOST_IMPORT_TEMPLATE2
|
||||||
|
#undef BOOST_IMPORT_TEMPLATE3
|
||||||
|
|
||||||
// The following 'operators' classes can only be used portably if the derived class
|
// The following 'operators' classes can only be used portably if the derived class
|
||||||
// declares ALL of the required member operators.
|
// declares ALL of the required member operators.
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
struct operators2
|
struct operators2
|
||||||
: less_than_comparable2<T,U
|
: totally_ordered2<T,U
|
||||||
, equality_comparable2<T,U
|
, integer_arithmetic2<T,U
|
||||||
, addable2<T,U
|
, bitwise2<T,U
|
||||||
, subtractable2<T,U
|
> > > {};
|
||||||
, multipliable2<T,U
|
|
||||||
, dividable2<T,U
|
|
||||||
, modable2<T,U
|
|
||||||
, orable2<T,U
|
|
||||||
, andable2<T,U
|
|
||||||
, xorable2<T,U
|
|
||||||
> > > > > > > > > > {};
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
template <class T, class U = T>
|
template <class T, class U = T>
|
||||||
@ -492,31 +681,47 @@ template <class T> struct operators<T, T>
|
|||||||
#else
|
#else
|
||||||
template <class T> struct operators
|
template <class T> struct operators
|
||||||
#endif
|
#endif
|
||||||
: less_than_comparable<T
|
: totally_ordered<T
|
||||||
, equality_comparable<T
|
, integer_arithmetic<T
|
||||||
, addable<T
|
, bitwise<T
|
||||||
, subtractable<T
|
, unit_steppable<T
|
||||||
, multipliable<T
|
> > > > {};
|
||||||
, dividable<T
|
|
||||||
, modable<T
|
|
||||||
, orable<T
|
|
||||||
, andable<T
|
|
||||||
, xorable<T
|
|
||||||
, incrementable<T
|
|
||||||
, decrementable<T
|
|
||||||
> > > > > > > > > > > > {};
|
|
||||||
|
|
||||||
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
|
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
|
||||||
|
// (Input and output iterator helpers contributed by Daryle Walker) -------//
|
||||||
|
// (Changed to use combined operator classes by Daryle Walker) ------------//
|
||||||
|
template <class T,
|
||||||
|
class V,
|
||||||
|
class D = std::ptrdiff_t,
|
||||||
|
class P = V const *,
|
||||||
|
class R = V const &>
|
||||||
|
struct input_iterator_helper
|
||||||
|
: equality_comparable1<T
|
||||||
|
, incrementable<T
|
||||||
|
, dereferenceable<T, P
|
||||||
|
, boost::iterator<std::input_iterator_tag, V, D, P, R
|
||||||
|
> > > > {};
|
||||||
|
|
||||||
|
template <class T,
|
||||||
|
class V = void,
|
||||||
|
class D = void,
|
||||||
|
class P = void,
|
||||||
|
class R = void>
|
||||||
|
struct output_iterator_helper
|
||||||
|
: incrementable<T
|
||||||
|
, boost::iterator<std::output_iterator_tag, V, D, P, R
|
||||||
|
> > {};
|
||||||
|
|
||||||
template <class T,
|
template <class T,
|
||||||
class V,
|
class V,
|
||||||
class D = std::ptrdiff_t,
|
class D = std::ptrdiff_t,
|
||||||
class P = V*,
|
class P = V*,
|
||||||
class R = V&>
|
class R = V&>
|
||||||
struct forward_iterator_helper
|
struct forward_iterator_helper
|
||||||
: equality_comparable<T
|
: equality_comparable1<T
|
||||||
, incrementable<T
|
, incrementable<T
|
||||||
, dereferenceable<T,P
|
, dereferenceable<T, P
|
||||||
, boost::iterator<std::forward_iterator_tag,V,D,P,R
|
, boost::iterator<std::forward_iterator_tag, V, D, P, R
|
||||||
> > > > {};
|
> > > > {};
|
||||||
|
|
||||||
template <class T,
|
template <class T,
|
||||||
@ -525,12 +730,11 @@ template <class T,
|
|||||||
class P = V*,
|
class P = V*,
|
||||||
class R = V&>
|
class R = V&>
|
||||||
struct bidirectional_iterator_helper
|
struct bidirectional_iterator_helper
|
||||||
: equality_comparable<T
|
: equality_comparable1<T
|
||||||
, incrementable<T
|
, unit_steppable<T
|
||||||
, decrementable<T
|
, dereferenceable<T, P
|
||||||
, dereferenceable<T,P
|
, boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
|
||||||
, boost::iterator<std::bidirectional_iterator_tag,V,D,P,R
|
> > > > {};
|
||||||
> > > > > {};
|
|
||||||
|
|
||||||
template <class T,
|
template <class T,
|
||||||
class V,
|
class V,
|
||||||
@ -538,22 +742,17 @@ template <class T,
|
|||||||
class P = V*,
|
class P = V*,
|
||||||
class R = V&>
|
class R = V&>
|
||||||
struct random_access_iterator_helper
|
struct random_access_iterator_helper
|
||||||
: equality_comparable<T
|
: totally_ordered1<T
|
||||||
, less_than_comparable<T
|
, unit_steppable<T
|
||||||
, incrementable<T
|
, dereferenceable<T, P
|
||||||
, decrementable<T
|
, additive2<T, D
|
||||||
, dereferenceable<T,P
|
, indexable<T, D, R
|
||||||
, addable2<T,D
|
, boost::iterator<std::random_access_iterator_tag, V, D, P, R
|
||||||
, subtractable2<T,D
|
> > > > > >
|
||||||
, indexable<T,D,R
|
|
||||||
, boost::iterator<std::random_access_iterator_tag,V,D,P,R
|
|
||||||
> > > > > > > > >
|
|
||||||
{
|
{
|
||||||
#ifndef __BORLANDC__
|
|
||||||
friend D requires_difference_operator(const T& x, const T& y) {
|
friend D requires_difference_operator(const T& x, const T& y) {
|
||||||
return x - y;
|
return x - y;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}; // random_access_iterator_helper
|
}; // random_access_iterator_helper
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
@ -9,16 +9,25 @@
|
|||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// Revision History
|
||||||
|
// 29 May 01 Factored implementation, added comparison tests, use Test Tools
|
||||||
|
// library (Daryle Walker)
|
||||||
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
||||||
|
|
||||||
#include <string>
|
#define BOOST_INCLUDE_MAIN
|
||||||
#include <iostream>
|
#include <boost/test/test_tools.hpp> // for main
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include <boost/operators.hpp>
|
#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT
|
||||||
using namespace boost;
|
#include <boost/cstdlib.hpp> // for boost::exit_success
|
||||||
|
#include <boost/operators.hpp> // for boost::random_access_iterator_helper
|
||||||
|
|
||||||
|
#include <cstddef> // for std::ptrdiff_t, std::size_t
|
||||||
|
#include <cstring> // for std::strcmp
|
||||||
|
#include <iostream> // for std::cout (std::endl, ends, and flush indirectly)
|
||||||
|
#include <string> // for std::string
|
||||||
|
#include <strstream> // for std::ostrstream
|
||||||
|
|
||||||
|
|
||||||
|
// Iterator test class
|
||||||
template <class T, class R, class P>
|
template <class T, class R, class P>
|
||||||
struct test_iter
|
struct test_iter
|
||||||
: public boost::random_access_iterator_helper<
|
: public boost::random_access_iterator_helper<
|
||||||
@ -29,7 +38,7 @@ struct test_iter
|
|||||||
typedef std::ptrdiff_t Distance;
|
typedef std::ptrdiff_t Distance;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
test_iter(T* i) : _i(i) { }
|
explicit test_iter(T* i =0) : _i(i) { }
|
||||||
test_iter(const self& x) : _i(x._i) { }
|
test_iter(const self& x) : _i(x._i) { }
|
||||||
self& operator=(const self& x) { _i = x._i; return *this; }
|
self& operator=(const self& x) { _i = x._i; return *this; }
|
||||||
Reference operator*() const { return *_i; }
|
Reference operator*() const { return *_i; }
|
||||||
@ -43,127 +52,280 @@ public:
|
|||||||
return x._i - y._i;
|
return x._i - y._i;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
T* _i;
|
P _i;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Iterator operator testing classes
|
||||||
int
|
class test_opr_base
|
||||||
main()
|
|
||||||
{
|
{
|
||||||
string array[] = { "apple", "orange", "pear", "peach", "grape", "plum" };
|
protected:
|
||||||
{
|
// Test data and types
|
||||||
test_iter<string,string&,string*> i = array,
|
BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u );
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
BOOST_STATIC_CONSTANT( std::size_t, scratch_length = 40u );
|
||||||
|
|
||||||
// Tests for all of the operators added by random_access_iterator_helper
|
typedef std::string fruit_array_type[ fruit_length ];
|
||||||
|
typedef char scratch_array_type[ scratch_length ];
|
||||||
|
|
||||||
// test i++
|
static fruit_array_type fruit;
|
||||||
while (i != ie)
|
static scratch_array_type scratch;
|
||||||
cout << *i++ << " ";
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i--
|
}; // test_opr_base
|
||||||
while (ie != i) {
|
|
||||||
ie--;
|
|
||||||
cout << *ie << " ";
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
|
||||||
|
|
||||||
// test i->m
|
template <typename T, typename R = T&, typename P = T*>
|
||||||
while (i != ie) {
|
class test_opr
|
||||||
cout << i->size() << " ";
|
: public test_opr_base
|
||||||
++i;
|
{
|
||||||
}
|
typedef test_opr<T, R, P> self_type;
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i + n
|
public:
|
||||||
while (i < ie) {
|
// Types
|
||||||
cout << *i << " ";
|
typedef T value_type;
|
||||||
i = i + 2;
|
typedef R reference;
|
||||||
}
|
typedef P pointer;
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test n + i
|
typedef test_iter<T, R, P> iter_type;
|
||||||
while (i < ie) {
|
|
||||||
cout << *i << " ";
|
|
||||||
i = ptrdiff_t(2) + i;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i - n
|
// Test controller
|
||||||
while (ie > i) {
|
static void master_test( char const name[] );
|
||||||
ie = ie - 2;
|
|
||||||
cout << *ie << " ";
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
|
||||||
|
|
||||||
// test i[n]
|
private:
|
||||||
for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
|
// Test data
|
||||||
cout << i[j] << " ";
|
static iter_type const fruit_begin, fruit_end;
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
test_iter<string, const string&, const string*> i = array,
|
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
|
||||||
|
|
||||||
// Tests for all of the operators added by random_access_iterator_helper
|
// Test parts
|
||||||
|
static void post_increment_test();
|
||||||
|
static void post_decrement_test();
|
||||||
|
static void indirect_referral_test();
|
||||||
|
static void offset_addition_test();
|
||||||
|
static void reverse_offset_addition_test();
|
||||||
|
static void offset_subtraction_test();
|
||||||
|
static void comparison_test();
|
||||||
|
static void indexing_test();
|
||||||
|
|
||||||
// test i++
|
}; // test_opr
|
||||||
while (i != ie)
|
|
||||||
cout << *i++ << " ";
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i--
|
|
||||||
while (ie != i) {
|
|
||||||
ie--;
|
|
||||||
cout << *ie << " ";
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
|
||||||
|
|
||||||
// test i->m
|
// Class-static data definitions
|
||||||
while (i != ie) {
|
typename test_opr_base::fruit_array_type
|
||||||
cout << i->size() << " ";
|
test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" };
|
||||||
++i;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i + n
|
typename test_opr_base::scratch_array_type
|
||||||
while (i < ie) {
|
test_opr_base::scratch = "";
|
||||||
cout << *i << " ";
|
|
||||||
i = i + 2;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test n + i
|
template <typename T, typename R, typename P>
|
||||||
while (i < ie) {
|
typename test_opr<T, R, P>::iter_type const
|
||||||
cout << *i << " ";
|
test_opr<T, R, P>::fruit_begin( fruit );
|
||||||
i = ptrdiff_t(2) + i;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i - n
|
template <typename T, typename R, typename P>
|
||||||
while (ie > i) {
|
typename test_opr<T, R, P>::iter_type const
|
||||||
ie = ie - 2;
|
test_opr<T, R, P>::fruit_end( fruit + fruit_length );
|
||||||
cout << *ie << " ";
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
|
||||||
|
|
||||||
// test i[n]
|
|
||||||
for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
|
// Main testing function
|
||||||
cout << i[j] << " ";
|
int
|
||||||
cout << endl;
|
test_main( int , char * [] )
|
||||||
}
|
{
|
||||||
return 0;
|
using std::string;
|
||||||
|
|
||||||
|
typedef test_opr<string, string &, string *> test1_type;
|
||||||
|
typedef test_opr<string, string const &, string const *> test2_type;
|
||||||
|
|
||||||
|
test1_type::master_test( "non-const string" );
|
||||||
|
test2_type::master_test( "const string" );
|
||||||
|
|
||||||
|
return boost::exit_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests for all of the operators added by random_access_iterator_helper
|
||||||
|
template <typename T, typename R, typename P>
|
||||||
|
void
|
||||||
|
test_opr<T, R, P>::master_test
|
||||||
|
(
|
||||||
|
char const name[]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cout << "Doing test run for " << name << '.' << std::endl;
|
||||||
|
|
||||||
|
post_increment_test();
|
||||||
|
post_decrement_test();
|
||||||
|
indirect_referral_test();
|
||||||
|
offset_addition_test();
|
||||||
|
reverse_offset_addition_test();
|
||||||
|
offset_subtraction_test();
|
||||||
|
comparison_test();
|
||||||
|
indexing_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test post-increment
|
||||||
|
template <typename T, typename R, typename P>
|
||||||
|
void
|
||||||
|
test_opr<T, R, P>::post_increment_test
|
||||||
|
(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cout << "\tDoing post-increment test." << std::endl;
|
||||||
|
|
||||||
|
std::ostrstream oss( scratch, scratch_length );
|
||||||
|
for ( iter_type i = fruit_begin ; i != fruit_end ; )
|
||||||
|
{
|
||||||
|
oss << *i++ << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << std::ends;
|
||||||
|
BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
|
||||||
|
== 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test post-decrement
|
||||||
|
template <typename T, typename R, typename P>
|
||||||
|
void
|
||||||
|
test_opr<T, R, P>::post_decrement_test
|
||||||
|
(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cout << "\tDoing post-decrement test." << std::endl;
|
||||||
|
|
||||||
|
std::ostrstream oss( scratch, scratch_length );
|
||||||
|
for ( iter_type i = fruit_end ; i != fruit_begin ; )
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
oss << *i << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << std::ends;
|
||||||
|
BOOST_TEST( std::strcmp(oss.str(), "plum grape peach pear orange apple ")
|
||||||
|
== 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test indirect structure referral
|
||||||
|
template <typename T, typename R, typename P>
|
||||||
|
void
|
||||||
|
test_opr<T, R, P>::indirect_referral_test
|
||||||
|
(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cout << "\tDoing indirect reference test." << std::endl;
|
||||||
|
|
||||||
|
std::ostrstream oss( scratch, scratch_length );
|
||||||
|
for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
|
||||||
|
{
|
||||||
|
oss << i->size() << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << std::ends;
|
||||||
|
BOOST_TEST( std::strcmp(oss.str(), "5 6 4 5 5 4 ") == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test offset addition
|
||||||
|
template <typename T, typename R, typename P>
|
||||||
|
void
|
||||||
|
test_opr<T, R, P>::offset_addition_test
|
||||||
|
(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cout << "\tDoing offset addition test." << std::endl;
|
||||||
|
|
||||||
|
std::ptrdiff_t const two = 2;
|
||||||
|
std::ostrstream oss( scratch, scratch_length );
|
||||||
|
for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two )
|
||||||
|
{
|
||||||
|
oss << *i << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << std::ends;
|
||||||
|
BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test offset addition, in reverse order
|
||||||
|
template <typename T, typename R, typename P>
|
||||||
|
void
|
||||||
|
test_opr<T, R, P>::reverse_offset_addition_test
|
||||||
|
(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cout << "\tDoing reverse offset addition test." << std::endl;
|
||||||
|
|
||||||
|
std::ptrdiff_t const two = 2;
|
||||||
|
std::ostrstream oss( scratch, scratch_length );
|
||||||
|
for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i )
|
||||||
|
{
|
||||||
|
oss << *i << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << std::ends;
|
||||||
|
BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test offset subtraction
|
||||||
|
template <typename T, typename R, typename P>
|
||||||
|
void
|
||||||
|
test_opr<T, R, P>::offset_subtraction_test
|
||||||
|
(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cout << "\tDoing offset subtraction test." << std::endl;
|
||||||
|
|
||||||
|
std::ptrdiff_t const two = 2;
|
||||||
|
std::ostrstream oss( scratch, scratch_length );
|
||||||
|
for ( iter_type i = fruit_end ; fruit_begin < i ; )
|
||||||
|
{
|
||||||
|
i = i - two;
|
||||||
|
if ( (fruit_begin < i) || (fruit_begin == i) )
|
||||||
|
{
|
||||||
|
oss << *i << ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << std::ends;
|
||||||
|
BOOST_TEST( std::strcmp(oss.str(), "grape pear apple ") == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test comparisons
|
||||||
|
template <typename T, typename R, typename P>
|
||||||
|
void
|
||||||
|
test_opr<T, R, P>::comparison_test
|
||||||
|
(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
using std::cout;
|
||||||
|
using std::ptrdiff_t;
|
||||||
|
|
||||||
|
cout << "\tDoing comparison tests.\n\t\tPass:";
|
||||||
|
|
||||||
|
for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
|
||||||
|
{
|
||||||
|
ptrdiff_t const i_offset = i - fruit_begin;
|
||||||
|
|
||||||
|
cout << ' ' << *i << std::flush;
|
||||||
|
for ( iter_type j = fruit_begin ; j != fruit_end ; ++j )
|
||||||
|
{
|
||||||
|
ptrdiff_t const j_offset = j - fruit_begin;
|
||||||
|
|
||||||
|
BOOST_TEST( (i != j) == (i_offset != j_offset) );
|
||||||
|
BOOST_TEST( (i > j) == (i_offset > j_offset) );
|
||||||
|
BOOST_TEST( (i <= j) == (i_offset <= j_offset) );
|
||||||
|
BOOST_TEST( (i >= j) == (i_offset >= j_offset) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test indexing
|
||||||
|
template <typename T, typename R, typename P>
|
||||||
|
void
|
||||||
|
test_opr<T, R, P>::indexing_test
|
||||||
|
(
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::cout << "\tDoing indexing test." << std::endl;
|
||||||
|
|
||||||
|
std::ostrstream oss( scratch, scratch_length );
|
||||||
|
for ( std::size_t k = 0u ; k < fruit_length ; ++k )
|
||||||
|
{
|
||||||
|
oss << fruit_begin[ k ] << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
oss << std::ends;
|
||||||
|
BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
|
||||||
|
== 0 );
|
||||||
}
|
}
|
||||||
|
1513
operators.htm
1513
operators.htm
File diff suppressed because it is too large
Load Diff
@ -8,18 +8,26 @@
|
|||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// Revision History
|
||||||
|
// 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)
|
||||||
// 04 Jun 00 Added regression test for a bug I found (David Abrahams)
|
// 04 Jun 00 Added regression test for a bug I found (David Abrahams)
|
||||||
// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
|
// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
|
||||||
// ?? ??? 00 Major update to randomly test all one- and two- argument forms by
|
// ?? ??? 00 Major update to randomly test all one- and two- argument forms by
|
||||||
// wrapping integral types and comparing the results of operations to
|
// wrapping integral types and comparing the results of operations
|
||||||
// the results for the raw types (David Abrahams)
|
// to the results for the raw types (David Abrahams)
|
||||||
// 12 Dec 99 Minor update, output confirmation message.
|
// 12 Dec 99 Minor update, output confirmation message.
|
||||||
// 15 Nov 99 Initial version
|
// 15 Nov 99 Initial version
|
||||||
|
|
||||||
#include <boost/operators.hpp>
|
#define BOOST_INCLUDE_MAIN
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
#include <boost/config.hpp> // for BOOST_MSVC
|
||||||
#include <boost/min_rand.hpp>
|
#include <boost/cstdlib.hpp> // for boost::exit_success
|
||||||
|
#include <boost/operators.hpp> // for the tested items
|
||||||
|
#include <boost/random/linear_congruential.hpp> // for boost::minstd_rand
|
||||||
|
#include <boost/test/test_tools.hpp> // for main
|
||||||
|
|
||||||
|
#include <iostream> // for std::cout (std::endl indirectly)
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -28,14 +36,18 @@ namespace
|
|||||||
int true_value(int x) { return x; }
|
int true_value(int x) { return x; }
|
||||||
long true_value(long x) { return x; }
|
long true_value(long x) { return x; }
|
||||||
signed char true_value(signed char x) { return x; }
|
signed char true_value(signed char x) { return x; }
|
||||||
|
short true_value(short x) { return x; }
|
||||||
unsigned int true_value(unsigned int x) { return x; }
|
unsigned int true_value(unsigned int x) { return x; }
|
||||||
unsigned long true_value(unsigned long x) { return x; }
|
unsigned long true_value(unsigned long x) { return x; }
|
||||||
unsigned char true_value(unsigned char x) { return x; }
|
unsigned char true_value(unsigned char x) { return x; }
|
||||||
|
unsigned short true_value(unsigned short x) { return x; }
|
||||||
|
|
||||||
// The use of operators<> here tended to obscure interactions with certain
|
// The use of operators<> here tended to obscure
|
||||||
// compiler bugs
|
// interactions with certain compiler bugs
|
||||||
template <class T>
|
template <class T>
|
||||||
class Wrapped1 : boost::operators<Wrapped1<T> >
|
class Wrapped1
|
||||||
|
: boost::operators<Wrapped1<T> >
|
||||||
|
, boost::shiftable<Wrapped1<T> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Wrapped1( T v = T() ) : _value(v) {}
|
explicit Wrapped1( T v = T() ) : _value(v) {}
|
||||||
@ -60,6 +72,10 @@ namespace
|
|||||||
{ _value &= x._value; return *this; }
|
{ _value &= x._value; return *this; }
|
||||||
Wrapped1& operator^=(const Wrapped1& x)
|
Wrapped1& operator^=(const Wrapped1& x)
|
||||||
{ _value ^= x._value; return *this; }
|
{ _value ^= x._value; return *this; }
|
||||||
|
Wrapped1& operator<<=(const Wrapped1& x)
|
||||||
|
{ _value <<= x._value; return *this; }
|
||||||
|
Wrapped1& operator>>=(const Wrapped1& x)
|
||||||
|
{ _value >>= x._value; return *this; }
|
||||||
Wrapped1& operator++() { ++_value; return *this; }
|
Wrapped1& operator++() { ++_value; return *this; }
|
||||||
Wrapped1& operator--() { --_value; return *this; }
|
Wrapped1& operator--() { --_value; return *this; }
|
||||||
|
|
||||||
@ -70,9 +86,11 @@ namespace
|
|||||||
T true_value(Wrapped1<T> x) { return x.value(); }
|
T true_value(Wrapped1<T> x) { return x.value(); }
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
class Wrapped2 :
|
class Wrapped2
|
||||||
boost::operators<Wrapped2<T, U> >,
|
: boost::operators<Wrapped2<T, U> >
|
||||||
boost::operators2<Wrapped2<T, U>, U>
|
, boost::operators2<Wrapped2<T, U>, U>
|
||||||
|
, boost::shiftable1<Wrapped2<T, U>
|
||||||
|
, boost::shiftable2<Wrapped2<T, U>, U > >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Wrapped2( T v = T() ) : _value(v) {}
|
explicit Wrapped2( T v = T() ) : _value(v) {}
|
||||||
@ -97,6 +115,10 @@ namespace
|
|||||||
{ _value &= x._value; return *this; }
|
{ _value &= x._value; return *this; }
|
||||||
Wrapped2& operator^=(const Wrapped2& x)
|
Wrapped2& operator^=(const Wrapped2& x)
|
||||||
{ _value ^= x._value; return *this; }
|
{ _value ^= x._value; return *this; }
|
||||||
|
Wrapped2& operator<<=(const Wrapped2& x)
|
||||||
|
{ _value <<= x._value; return *this; }
|
||||||
|
Wrapped2& operator>>=(const Wrapped2& x)
|
||||||
|
{ _value >>= x._value; return *this; }
|
||||||
Wrapped2& operator++() { ++_value; return *this; }
|
Wrapped2& operator++() { ++_value; return *this; }
|
||||||
Wrapped2& operator--() { --_value; return *this; }
|
Wrapped2& operator--() { --_value; return *this; }
|
||||||
|
|
||||||
@ -111,6 +133,8 @@ namespace
|
|||||||
Wrapped2& operator|=(U u) { _value |= u; return *this; }
|
Wrapped2& operator|=(U u) { _value |= u; return *this; }
|
||||||
Wrapped2& operator&=(U u) { _value &= u; return *this; }
|
Wrapped2& operator&=(U u) { _value &= u; return *this; }
|
||||||
Wrapped2& operator^=(U u) { _value ^= u; return *this; }
|
Wrapped2& operator^=(U u) { _value ^= u; return *this; }
|
||||||
|
Wrapped2& operator<<=(U u) { _value <<= u; return *this; }
|
||||||
|
Wrapped2& operator>>=(U u) { _value >>= u; return *this; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T _value;
|
T _value;
|
||||||
@ -118,203 +142,268 @@ namespace
|
|||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
T true_value(Wrapped2<T,U> x) { return x.value(); }
|
T true_value(Wrapped2<T,U> x) { return x.value(); }
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class Wrapped3
|
||||||
|
: boost::equivalent<Wrapped3<T> >
|
||||||
|
, boost::partially_ordered<Wrapped3<T> >
|
||||||
|
, boost::equality_comparable<Wrapped3<T> >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Wrapped3( T v = T() ) : _value(v) {}
|
||||||
|
T value() const { return _value; }
|
||||||
|
|
||||||
|
bool operator<(const Wrapped3& x) const { return _value < x._value; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T _value;
|
||||||
|
};
|
||||||
|
template <class T>
|
||||||
|
T true_value(Wrapped3<T> x) { return x.value(); }
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
class Wrapped4
|
||||||
|
: boost::equality_comparable1<Wrapped4<T, U>
|
||||||
|
, boost::equivalent1<Wrapped4<T, U>
|
||||||
|
, boost::partially_ordered1<Wrapped4<T, U> > > >
|
||||||
|
, boost::partially_ordered2<Wrapped4<T, U>, U
|
||||||
|
, boost::equivalent2<Wrapped4<T, U>, U
|
||||||
|
, boost::equality_comparable2<Wrapped4<T, U>, U> > >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Wrapped4( T v = T() ) : _value(v) {}
|
||||||
|
T value() const { return _value; }
|
||||||
|
|
||||||
|
bool operator<(const Wrapped4& x) const { return _value < x._value; }
|
||||||
|
|
||||||
|
bool operator<(U u) const { return _value < u; }
|
||||||
|
bool operator>(U u) const { return _value > u; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T _value;
|
||||||
|
};
|
||||||
|
template <class T, class U>
|
||||||
|
T true_value(Wrapped4<T,U> x) { return x.value(); }
|
||||||
|
|
||||||
// MyInt uses only the single template-argument form of all_operators<>
|
// MyInt uses only the single template-argument form of all_operators<>
|
||||||
typedef Wrapped1<int> MyInt;
|
typedef Wrapped1<int> MyInt;
|
||||||
|
|
||||||
typedef Wrapped2<long, long> MyLong;
|
typedef Wrapped2<long, long> MyLong;
|
||||||
|
|
||||||
|
typedef Wrapped3<signed char> MyChar;
|
||||||
|
|
||||||
|
typedef Wrapped4<short, short> MyShort;
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert(true_value(y1) == true_value(y2));
|
BOOST_TEST( true_value(y1) == true_value(y2) );
|
||||||
assert(true_value(x1) == true_value(x2));
|
BOOST_TEST( true_value(x1) == true_value(x2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert((x1 < y1) == (x2 < y2));
|
BOOST_TEST( (x1 < y1) == (x2 < y2) );
|
||||||
assert((x1 <= y1) == (x2 <= y2));
|
BOOST_TEST( (x1 <= y1) == (x2 <= y2) );
|
||||||
assert((x1 >= y1) == (x2 >= y2));
|
BOOST_TEST( (x1 >= y1) == (x2 >= y2) );
|
||||||
assert((x1 > y1) == (x2 > y2));
|
BOOST_TEST( (x1 > y1) == (x2 > y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_less_than_comparable_aux(x1, y1, x2, y2);
|
test_less_than_comparable_aux( x1, y1, x2, y2 );
|
||||||
test_less_than_comparable_aux(y1, x1, y2, x2);
|
test_less_than_comparable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert((x1 == y1) == (x2 == y2));
|
BOOST_TEST( (x1 == y1) == (x2 == y2) );
|
||||||
assert((x1 != y1) == (x2 != y2));
|
BOOST_TEST( (x1 != y1) == (x2 != y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_equality_comparable_aux(x1, y1, x2, y2);
|
test_equality_comparable_aux( x1, y1, x2, y2 );
|
||||||
test_equality_comparable_aux(y1, x1, y2, x2);
|
test_equality_comparable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert((x1 * y1).value() == (x2 * y2));
|
BOOST_TEST( (x1 * y1).value() == (x2 * y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_multipliable_aux(x1, y1, x2, y2);
|
test_multipliable_aux( x1, y1, x2, y2 );
|
||||||
test_multipliable_aux(y1, x1, y2, x2);
|
test_multipliable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert((x1 + y1).value() == (x2 + y2));
|
BOOST_TEST( (x1 + y1).value() == (x2 + y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_addable_aux(x1, y1, x2, y2);
|
test_addable_aux( x1, y1, x2, y2 );
|
||||||
test_addable_aux(y1, x1, y2, x2);
|
test_addable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
assert((x1 - y1).value() == x2 - y2);
|
BOOST_TEST( (x1 - y1).value() == (x2 - y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
if (y2 != 0)
|
if ( y2 != 0 )
|
||||||
assert((x1 / y1).value() == x2 / y2);
|
BOOST_TEST( (x1 / y1).value() == (x2 / y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
if (y2 != 0)
|
if ( y2 != 0 )
|
||||||
assert((x1 / y1).value() == x2 / y2);
|
BOOST_TEST( (x1 % y1).value() == (x2 % y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert((x1 ^ y1).value() == (x2 ^ y2));
|
BOOST_TEST( (x1 ^ y1).value() == (x2 ^ y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_xorable_aux(x1, y1, x2, y2);
|
test_xorable_aux( x1, y1, x2, y2 );
|
||||||
test_xorable_aux(y1, x1, y2, x2);
|
test_xorable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert((x1 & y1).value() == (x2 & y2));
|
BOOST_TEST( (x1 & y1).value() == (x2 & y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_andable_aux(x1, y1, x2, y2);
|
test_andable_aux( x1, y1, x2, y2 );
|
||||||
test_andable_aux(y1, x1, y2, x2);
|
test_andable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert((x1 | y1).value() == (x2 | y2));
|
BOOST_TEST( (x1 | y1).value() == (x2 | y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_orable_aux(x1, y1, x2, y2);
|
test_orable_aux( x1, y1, x2, y2 );
|
||||||
test_orable_aux(y1, x1, y2, x2);
|
test_orable_aux( y1, x1, y2, x2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
|
void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
|
{
|
||||||
|
sanity_check( x1, y1, x2, y2 );
|
||||||
|
BOOST_TEST( (x1 << y1).value() == (x2 << y2) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
|
void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
|
{
|
||||||
|
sanity_check( x1, y1, x2, y2 );
|
||||||
|
BOOST_TEST( (x1 >> y1).value() == (x2 >> y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class X2>
|
template <class X1, class X2>
|
||||||
void test_incrementable(X1 x1, X2 x2)
|
void test_incrementable(X1 x1, X2 x2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, x1, x2, x2);
|
sanity_check( x1, x1, x2, x2 );
|
||||||
assert(x1++.value() == x2++);
|
BOOST_TEST( (x1++).value() == x2++ );
|
||||||
assert(x1.value() == x2);
|
BOOST_TEST( x1.value() == x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class X2>
|
template <class X1, class X2>
|
||||||
void test_decrementable(X1 x1, X2 x2)
|
void test_decrementable(X1 x1, X2 x2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, x1, x2, x2);
|
sanity_check( x1, x1, x2, x2 );
|
||||||
assert(x1--.value() == x2--);
|
BOOST_TEST( (x1--).value() == x2-- );
|
||||||
assert(x1.value() == x2);
|
BOOST_TEST( x1.value() == x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
test_less_than_comparable(x1, y1, x2, y2);
|
test_less_than_comparable( x1, y1, x2, y2 );
|
||||||
test_equality_comparable(x1, y1, x2, y2);
|
test_equality_comparable( x1, y1, x2, y2 );
|
||||||
test_multipliable(x1, y1, x2, y2);
|
test_multipliable( x1, y1, x2, y2 );
|
||||||
test_addable(x1, y1, x2, y2);
|
test_addable( x1, y1, x2, y2 );
|
||||||
test_subtractable(x1, y1, x2, y2);
|
test_subtractable( x1, y1, x2, y2 );
|
||||||
test_dividable(x1, y1, x2, y2);
|
test_dividable( x1, y1, x2, y2 );
|
||||||
test_modable(x1, y1, x2, y2);
|
test_modable( x1, y1, x2, y2 );
|
||||||
test_xorable(x1, y1, x2, y2);
|
test_xorable( x1, y1, x2, y2 );
|
||||||
test_andable(x1, y1, x2, y2);
|
test_andable( x1, y1, x2, y2 );
|
||||||
test_orable(x1, y1, x2, y2);
|
test_orable( x1, y1, x2, y2 );
|
||||||
test_incrementable(x1, x2);
|
test_left_shiftable( x1, y1, x2, y2 );
|
||||||
test_decrementable(x1, x2);
|
test_right_shiftable( x1, y1, x2, y2 );
|
||||||
|
test_incrementable( x1, x2 );
|
||||||
|
test_decrementable( x1, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Big, class Small>
|
template <class Big, class Small>
|
||||||
struct tester
|
struct tester
|
||||||
{
|
{
|
||||||
void operator()(boost::min_rand& randomizer) const
|
void operator()(boost::minstd_rand& randomizer) const
|
||||||
{
|
{
|
||||||
Big b1 = Big(randomizer());
|
Big b1 = Big( randomizer() );
|
||||||
Big b2 = Big(randomizer());
|
Big b2 = Big( randomizer() );
|
||||||
Small s = Small(randomizer());
|
Small s = Small( randomizer() );
|
||||||
|
|
||||||
test_all(Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2);
|
test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 );
|
||||||
test_all(Wrapped2<Big, Small>(b1), s, b1, s);
|
test_all( Wrapped2<Big, Small>(b1), s, b1, s );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// added as a regression test. We had a bug which this uncovered.
|
// added as a regression test. We had a bug which this uncovered.
|
||||||
struct Point
|
struct Point
|
||||||
: boost::addable<Point,
|
: boost::addable<Point
|
||||||
boost::subtractable<Point> >
|
, boost::subtractable<Point> >
|
||||||
{
|
{
|
||||||
Point( int h, int v ) : h(h), v(v) {}
|
Point( int h, int v ) : h(h), v(v) {}
|
||||||
Point() :h(0), v(0) {}
|
Point() :h(0), v(0) {}
|
||||||
const Point& operator+=( const Point& rhs ) { h += rhs.h; v += rhs.v; return *this; }
|
const Point& operator+=( const Point& rhs )
|
||||||
const Point& operator-=( const Point& rhs ) { h -= rhs.h; v -= rhs.v; return *this; }
|
{ h += rhs.h; v += rhs.v; return *this; }
|
||||||
|
const Point& operator-=( const Point& rhs )
|
||||||
|
{ h -= rhs.h; v -= rhs.v; return *this; }
|
||||||
|
|
||||||
int h;
|
int h;
|
||||||
int v;
|
int v;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
|
|
||||||
|
|
||||||
@ -340,20 +429,25 @@ template Wrapped2<unsigned long, unsigned char>;
|
|||||||
template Wrapped2<unsigned long, unsigned long>;
|
template Wrapped2<unsigned long, unsigned long>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
|
||||||
#error This program is pointless when NDEBUG disables assert()!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main()
|
|
||||||
|
int
|
||||||
|
test_main( int , char * [] )
|
||||||
{
|
{
|
||||||
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
// Regression test.
|
// Regression test.
|
||||||
Point x;
|
Point x;
|
||||||
x = x + Point(3, 4);
|
x = x + Point(3, 4);
|
||||||
x = x - Point(3, 4);
|
x = x - Point(3, 4);
|
||||||
|
|
||||||
|
cout << "Created point, and operated on it." << endl;
|
||||||
|
|
||||||
for (int n = 0; n < 10000; ++n)
|
for (int n = 0; n < 10000; ++n)
|
||||||
{
|
{
|
||||||
boost::min_rand r;
|
boost::minstd_rand r;
|
||||||
tester<long, int>()(r);
|
tester<long, int>()(r);
|
||||||
tester<long, signed char>()(r);
|
tester<long, signed char>()(r);
|
||||||
tester<long, long>()(r);
|
tester<long, long>()(r);
|
||||||
@ -367,115 +461,197 @@ int main()
|
|||||||
tester<unsigned int, unsigned char>()(r);
|
tester<unsigned int, unsigned char>()(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cout << "Did random tester loop." << endl;
|
||||||
|
|
||||||
MyInt i1(1);
|
MyInt i1(1);
|
||||||
MyInt i2(2);
|
MyInt i2(2);
|
||||||
MyInt i;
|
MyInt i;
|
||||||
|
|
||||||
assert( i1.value() == 1 );
|
BOOST_TEST( i1.value() == 1 );
|
||||||
assert( i2.value() == 2 );
|
BOOST_TEST( i2.value() == 2 );
|
||||||
assert( i.value() == 0 );
|
BOOST_TEST( i.value() == 0 );
|
||||||
|
|
||||||
i = i2;
|
cout << "Created MyInt objects.\n";
|
||||||
assert( i.value() == 2 );
|
|
||||||
assert( i2 == i );
|
|
||||||
assert( i1 != i2 );
|
|
||||||
assert( i1 < i2 );
|
|
||||||
assert( i1 <= i2 );
|
|
||||||
assert( i <= i2 );
|
|
||||||
assert( i2 > i1 );
|
|
||||||
assert( i2 >= i1 );
|
|
||||||
assert( i2 >= i );
|
|
||||||
|
|
||||||
i = i1 + i2; assert( i.value() == 3 );
|
PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) );
|
||||||
i = i + i2; assert( i.value() == 5 );
|
|
||||||
i = i - i1; assert( i.value() == 4 );
|
BOOST_TEST( i2 == i );
|
||||||
i = i * i2; assert( i.value() == 8 );
|
BOOST_TEST( i1 != i2 );
|
||||||
i = i / i2; assert( i.value() == 4 );
|
BOOST_TEST( i1 < i2 );
|
||||||
i = i % (i - i1); assert( i.value() == 1 );
|
BOOST_TEST( i1 <= i2 );
|
||||||
i = i2 + i2; assert( i.value() == 4 );
|
BOOST_TEST( i <= i2 );
|
||||||
i = i1 | i2 | i; assert( i.value() == 7 );
|
BOOST_TEST( i2 > i1 );
|
||||||
i = i & i2; assert( i.value() == 2 );
|
BOOST_TEST( i2 >= i1 );
|
||||||
i = i + i1; assert( i.value() == 3 );
|
BOOST_TEST( i2 >= i );
|
||||||
i = i ^ i1; assert( i.value() == 2 );
|
|
||||||
i = (i+i1)*(i2|i1); assert( i.value() == 9 );
|
PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) );
|
||||||
|
|
||||||
|
PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) );
|
||||||
|
PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) );
|
||||||
|
|
||||||
|
cout << "Performed tests on MyInt objects.\n";
|
||||||
|
|
||||||
MyLong j1(1);
|
MyLong j1(1);
|
||||||
MyLong j2(2);
|
MyLong j2(2);
|
||||||
MyLong j;
|
MyLong j;
|
||||||
|
|
||||||
assert( j1.value() == 1 );
|
BOOST_TEST( j1.value() == 1 );
|
||||||
assert( j2.value() == 2 );
|
BOOST_TEST( j2.value() == 2 );
|
||||||
assert( j.value() == 0 );
|
BOOST_TEST( j.value() == 0 );
|
||||||
|
|
||||||
j = j2;
|
cout << "Created MyLong objects.\n";
|
||||||
assert( j.value() == 2 );
|
|
||||||
|
|
||||||
assert( j2 == j );
|
PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) );
|
||||||
assert( 2 == j );
|
|
||||||
assert( j2 == 2 );
|
|
||||||
assert( j == j2 );
|
|
||||||
assert( j1 != j2 );
|
|
||||||
assert( j1 != 2 );
|
|
||||||
assert( 1 != j2 );
|
|
||||||
assert( j1 < j2 );
|
|
||||||
assert( 1 < j2 );
|
|
||||||
assert( j1 < 2 );
|
|
||||||
assert( j1 <= j2 );
|
|
||||||
assert( 1 <= j2 );
|
|
||||||
assert( j1 <= j );
|
|
||||||
assert( j <= j2 );
|
|
||||||
assert( 2 <= j2 );
|
|
||||||
assert( j <= 2 );
|
|
||||||
assert( j2 > j1 );
|
|
||||||
assert( 2 > j1 );
|
|
||||||
assert( j2 > 1 );
|
|
||||||
assert( j2 >= j1 );
|
|
||||||
assert( 2 >= j1 );
|
|
||||||
assert( j2 >= 1 );
|
|
||||||
assert( j2 >= j );
|
|
||||||
assert( 2 >= j );
|
|
||||||
assert( j2 >= 2 );
|
|
||||||
|
|
||||||
assert( (j1 + 2) == 3 );
|
BOOST_TEST( j2 == j );
|
||||||
assert( (1 + j2) == 3 );
|
BOOST_TEST( 2 == j );
|
||||||
j = j1 + j2; assert( j.value() == 3 );
|
BOOST_TEST( j2 == 2 );
|
||||||
|
BOOST_TEST( j == j2 );
|
||||||
|
BOOST_TEST( j1 != j2 );
|
||||||
|
BOOST_TEST( j1 != 2 );
|
||||||
|
BOOST_TEST( 1 != j2 );
|
||||||
|
BOOST_TEST( j1 < j2 );
|
||||||
|
BOOST_TEST( 1 < j2 );
|
||||||
|
BOOST_TEST( j1 < 2 );
|
||||||
|
BOOST_TEST( j1 <= j2 );
|
||||||
|
BOOST_TEST( 1 <= j2 );
|
||||||
|
BOOST_TEST( j1 <= j );
|
||||||
|
BOOST_TEST( j <= j2 );
|
||||||
|
BOOST_TEST( 2 <= j2 );
|
||||||
|
BOOST_TEST( j <= 2 );
|
||||||
|
BOOST_TEST( j2 > j1 );
|
||||||
|
BOOST_TEST( 2 > j1 );
|
||||||
|
BOOST_TEST( j2 > 1 );
|
||||||
|
BOOST_TEST( j2 >= j1 );
|
||||||
|
BOOST_TEST( 2 >= j1 );
|
||||||
|
BOOST_TEST( j2 >= 1 );
|
||||||
|
BOOST_TEST( j2 >= j );
|
||||||
|
BOOST_TEST( 2 >= j );
|
||||||
|
BOOST_TEST( j2 >= 2 );
|
||||||
|
|
||||||
assert( (j + 2) == 5 );
|
BOOST_TEST( (j1 + 2) == 3 );
|
||||||
assert( (3 + j2) == 5 );
|
BOOST_TEST( (1 + j2) == 3 );
|
||||||
j = j + j2; assert( j.value() == 5 );
|
PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) );
|
||||||
|
|
||||||
assert( (j - 1) == 4 );
|
BOOST_TEST( (j + 2) == 5 );
|
||||||
j = j - j1; assert( j.value() == 4 );
|
BOOST_TEST( (3 + j2) == 5 );
|
||||||
|
PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
|
||||||
|
|
||||||
assert( (j * 2) == 8 );
|
BOOST_TEST( (j - 1) == 4 );
|
||||||
assert( (4 * j2) == 8 );
|
PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
|
||||||
j = j * j2; assert( j.value() == 8 );
|
|
||||||
|
|
||||||
assert( (j / 2) == 4 );
|
BOOST_TEST( (j * 2) == 8 );
|
||||||
j = j / j2; assert( j.value() == 4 );
|
BOOST_TEST( (4 * j2) == 8 );
|
||||||
|
PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
|
||||||
|
|
||||||
assert( (j % 3) == 1 );
|
BOOST_TEST( (j / 2) == 4 );
|
||||||
j = j % (j - j1); assert( j.value() == 1 );
|
PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) );
|
||||||
|
|
||||||
j = j2 + j2; assert( j.value() == 4 );
|
BOOST_TEST( (j % 3) == 1 );
|
||||||
|
PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) );
|
||||||
|
|
||||||
assert( (1 | j2 | j) == 7 );
|
PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) );
|
||||||
assert( (j1 | 2 | j) == 7 );
|
|
||||||
assert( (j1 | j2 | 4) == 7 );
|
|
||||||
j = j1 | j2 | j; assert( j.value() == 7 );
|
|
||||||
|
|
||||||
assert( (7 & j2) == 2 );
|
BOOST_TEST( (1 | j2 | j) == 7 );
|
||||||
assert( (j & 2) == 2 );
|
BOOST_TEST( (j1 | 2 | j) == 7 );
|
||||||
j = j & j2; assert( j.value() == 2 );
|
BOOST_TEST( (j1 | j2 | 4) == 7 );
|
||||||
|
PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) );
|
||||||
|
|
||||||
j = j | j1; assert( j.value() == 3 );
|
BOOST_TEST( (7 & j2) == 2 );
|
||||||
|
BOOST_TEST( (j & 2) == 2 );
|
||||||
|
PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) );
|
||||||
|
|
||||||
assert( (3 ^ j1) == 2 );
|
PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) );
|
||||||
assert( (j ^ 1) == 2 );
|
|
||||||
j = j ^ j1; assert( j.value() == 2 );
|
|
||||||
|
|
||||||
j = (j+j1)*(j2|j1); assert( j.value() == 9 );
|
BOOST_TEST( (3 ^ j1) == 2 );
|
||||||
|
BOOST_TEST( (j ^ 1) == 2 );
|
||||||
|
PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) );
|
||||||
|
|
||||||
std::cout << "0 errors detected\n";
|
PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) );
|
||||||
return 0;
|
|
||||||
|
BOOST_TEST( (j1 << 2) == 4 );
|
||||||
|
BOOST_TEST( (j2 << 1) == 4 );
|
||||||
|
PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) );
|
||||||
|
|
||||||
|
BOOST_TEST( (j >> 2) == 1 );
|
||||||
|
BOOST_TEST( (j2 >> 1) == 1 );
|
||||||
|
PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) );
|
||||||
|
|
||||||
|
cout << "Performed tests on MyLong objects.\n";
|
||||||
|
|
||||||
|
MyChar k1(1);
|
||||||
|
MyChar k2(2);
|
||||||
|
MyChar k;
|
||||||
|
|
||||||
|
BOOST_TEST( k1.value() == 1 );
|
||||||
|
BOOST_TEST( k2.value() == 2 );
|
||||||
|
BOOST_TEST( k.value() == 0 );
|
||||||
|
|
||||||
|
cout << "Created MyChar objects.\n";
|
||||||
|
|
||||||
|
PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) );
|
||||||
|
|
||||||
|
BOOST_TEST( k2 == k );
|
||||||
|
BOOST_TEST( k1 != k2 );
|
||||||
|
BOOST_TEST( k1 < k2 );
|
||||||
|
BOOST_TEST( k1 <= k2 );
|
||||||
|
BOOST_TEST( k <= k2 );
|
||||||
|
BOOST_TEST( k2 > k1 );
|
||||||
|
BOOST_TEST( k2 >= k1 );
|
||||||
|
BOOST_TEST( k2 >= k );
|
||||||
|
|
||||||
|
cout << "Performed tests on MyChar objects.\n";
|
||||||
|
|
||||||
|
MyShort l1(1);
|
||||||
|
MyShort l2(2);
|
||||||
|
MyShort l;
|
||||||
|
|
||||||
|
BOOST_TEST( l1.value() == 1 );
|
||||||
|
BOOST_TEST( l2.value() == 2 );
|
||||||
|
BOOST_TEST( l.value() == 0 );
|
||||||
|
|
||||||
|
cout << "Created MyShort objects.\n";
|
||||||
|
|
||||||
|
PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) );
|
||||||
|
|
||||||
|
BOOST_TEST( l2 == l );
|
||||||
|
BOOST_TEST( 2 == l );
|
||||||
|
BOOST_TEST( l2 == 2 );
|
||||||
|
BOOST_TEST( l == l2 );
|
||||||
|
BOOST_TEST( l1 != l2 );
|
||||||
|
BOOST_TEST( l1 != 2 );
|
||||||
|
BOOST_TEST( 1 != l2 );
|
||||||
|
BOOST_TEST( l1 < l2 );
|
||||||
|
BOOST_TEST( 1 < l2 );
|
||||||
|
BOOST_TEST( l1 < 2 );
|
||||||
|
BOOST_TEST( l1 <= l2 );
|
||||||
|
BOOST_TEST( 1 <= l2 );
|
||||||
|
BOOST_TEST( l1 <= l );
|
||||||
|
BOOST_TEST( l <= l2 );
|
||||||
|
BOOST_TEST( 2 <= l2 );
|
||||||
|
BOOST_TEST( l <= 2 );
|
||||||
|
BOOST_TEST( l2 > l1 );
|
||||||
|
BOOST_TEST( 2 > l1 );
|
||||||
|
BOOST_TEST( l2 > 1 );
|
||||||
|
BOOST_TEST( l2 >= l1 );
|
||||||
|
BOOST_TEST( 2 >= l1 );
|
||||||
|
BOOST_TEST( l2 >= 1 );
|
||||||
|
BOOST_TEST( l2 >= l );
|
||||||
|
BOOST_TEST( 2 >= l );
|
||||||
|
BOOST_TEST( l2 >= 2 );
|
||||||
|
|
||||||
|
cout << "Performed tests on MyShort objects.\n";
|
||||||
|
|
||||||
|
return boost::exit_success;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user