mirror of
https://github.com/boostorg/utility.git
synced 2025-05-08 18:34:02 +00:00
committing Daryle and Helmut's changes
[SVN r11813]
This commit is contained in:
parent
3e9d0f80c2
commit
18944572b7
@ -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 <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct subtractable2_left : B
|
||||
{
|
||||
friend T operator-(const U& x, const T& y)
|
||||
{ T result(x); return result -= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct subtractable1 : B
|
||||
{
|
||||
@ -180,6 +199,13 @@ struct dividable2 : B
|
||||
friend T operator/(T x, const U& y) { return x /= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct dividable2_left : B
|
||||
{
|
||||
friend T operator/(const U& x, const T& y)
|
||||
{ T result(x); return result /= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct dividable1 : B
|
||||
{
|
||||
@ -192,6 +218,13 @@ struct modable2 : B
|
||||
friend T operator%(T x, const U& y) { return x %= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct modable2_left : B
|
||||
{
|
||||
friend T operator%(const U& x, const T& y)
|
||||
{ T result(x); return result %= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct modable1 : B
|
||||
{
|
||||
@ -463,12 +496,121 @@ struct shiftable1
|
||||
, right_shiftable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ring_operators2
|
||||
: additive2<T, U
|
||||
, subtractable2_left<T, U
|
||||
, multipliable2<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ring_operators1
|
||||
: additive1<T
|
||||
, multipliable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ordered_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, totally_ordered2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ordered_ring_operators1
|
||||
: ring_operators1<T
|
||||
, totally_ordered1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct field_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct field_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ordered_field_operators2
|
||||
: field_operators2<T, U
|
||||
, totally_ordered2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ordered_field_operators1
|
||||
: field_operators1<T
|
||||
, totally_ordered1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct euclidian_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U
|
||||
, modable2<T, U
|
||||
, modable2_left<T, U, B
|
||||
> > > > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct euclidian_ring_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T
|
||||
, modable1<T, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ordered_euclidian_ring_operators2
|
||||
: totally_ordered2<T, U
|
||||
, euclidian_ring_operators2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ordered_euclidian_ring_operators1
|
||||
: totally_ordered1<T
|
||||
, euclidian_ring_operators1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||
struct input_iteratable
|
||||
: equality_comparable1<T
|
||||
, incrementable<T
|
||||
, dereferenceable<T, P, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct output_iteratable
|
||||
: incrementable<T, B
|
||||
> {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||
struct forward_iteratable
|
||||
: input_iteratable<T, P, B
|
||||
> {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||
struct bidirectional_iteratable
|
||||
: forward_iteratable<T, P
|
||||
, decrementable<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base>
|
||||
struct random_access_iteratable
|
||||
: bidirectional_iteratable<T, P
|
||||
, totally_ordered1<T
|
||||
, additive2<T, D
|
||||
, indexable<T, D, R, B
|
||||
> > > > {};
|
||||
|
||||
#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 <class T, class U, class V, class W, class B = ::boost::detail::empty_base> \
|
||||
struct template_name : ::template_name<T, U, V, W, B> {};
|
||||
|
||||
# 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> {};
|
||||
@ -542,6 +690,15 @@ template<class T> 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<class T, class U, class V, class W, class B> \
|
||||
struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
|
||||
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 <class T,
|
||||
class P = V const *,
|
||||
class R = V const &>
|
||||
struct input_iterator_helper
|
||||
: equality_comparable1<T
|
||||
, incrementable<T
|
||||
, dereferenceable<T, P
|
||||
: input_iteratable<T, P
|
||||
, boost::iterator<std::input_iterator_tag, V, D, P, R
|
||||
> > > > {};
|
||||
> > {};
|
||||
|
||||
template<class Derived>
|
||||
template<class T>
|
||||
struct output_iterator_helper
|
||||
: boost::incrementable<Derived
|
||||
: output_iteratable<T
|
||||
, boost::iterator<std::output_iterator_tag, void, void, void, void
|
||||
> >
|
||||
{
|
||||
Derived& operator*() { return static_cast<Derived&>(*this); }
|
||||
Derived& operator++() { return static_cast<Derived&>(*this); }
|
||||
T& operator*() { return static_cast<T&>(*this); }
|
||||
T& operator++() { return static_cast<T&>(*this); }
|
||||
};
|
||||
|
||||
template <class T,
|
||||
@ -721,11 +894,9 @@ template <class T,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct forward_iterator_helper
|
||||
: equality_comparable1<T
|
||||
, incrementable<T
|
||||
, dereferenceable<T, P
|
||||
: forward_iteratable<T, P
|
||||
, boost::iterator<std::forward_iterator_tag, V, D, P, R
|
||||
> > > > {};
|
||||
> > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
@ -733,11 +904,9 @@ template <class T,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct bidirectional_iterator_helper
|
||||
: equality_comparable1<T
|
||||
, unit_steppable<T
|
||||
, dereferenceable<T, P
|
||||
: bidirectional_iteratable<T, P
|
||||
, boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
|
||||
> > > > {};
|
||||
> > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
@ -745,13 +914,9 @@ template <class T,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct random_access_iterator_helper
|
||||
: totally_ordered1<T
|
||||
, unit_steppable<T
|
||||
, dereferenceable<T, P
|
||||
, additive2<T, D
|
||||
, indexable<T, D, R
|
||||
: random_access_iteratable<T, P, D, R
|
||||
, boost::iterator<std::random_access_iterator_tag, V, D, P, R
|
||||
> > > > > >
|
||||
> >
|
||||
{
|
||||
friend D requires_difference_operator(const T& x, const T& y) {
|
||||
return x - y;
|
||||
|
317
operators.htm
317
operators.htm
@ -30,7 +30,11 @@ provided by the class.</p>
|
||||
</ul></li>
|
||||
<li><a href="#usage">Usage</a>
|
||||
<ul>
|
||||
<li><a href="#two_arg">Two-Argument Template Forms</a></li>
|
||||
<li><a href="#two_arg">Two-Argument Template Forms</a>
|
||||
<ul>
|
||||
<li><a href="#two_arg_gen">General Considerations</a></li>
|
||||
<li><a href="#mixed_arithmetics">Mixed arithmetics</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#chaining">Base Class Chaining and Object Size</a></li>
|
||||
<li><a href="#explicit_instantiation">Separate, Explicit
|
||||
Instantiation</a></li>
|
||||
@ -39,7 +43,10 @@ provided by the class.</p>
|
||||
<li><a href="#example">Example</a></li>
|
||||
<li><a href="#arithmetic">Arithmetic operators</a>
|
||||
<ul>
|
||||
<li><a href="#smpl_oprs">Simple Arithmetic Operators</a></li>
|
||||
<li><a href="#smpl_oprs">Simple Arithmetic Operators</a>
|
||||
<ul>
|
||||
<li><a href="#ordering">Ordering Note</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#grpd_oprs">Grouped Arithmetic Operators</a></li>
|
||||
<li><a href="#ex_oprs">Example Templates</a></li>
|
||||
<li><a href="#a_demo">Arithmetic Operators Demonstration
|
||||
@ -49,8 +56,12 @@ provided by the class.</p>
|
||||
Helpers</a>
|
||||
<ul>
|
||||
<li><a href="#dereference">Dereference operators</a></li>
|
||||
<li><a href="#iterator">Iterator Helpers</a></li>
|
||||
<li><a href="#iterator_helpers_notes">Iterator Helper Notes</a></li>
|
||||
<li><a href="#grpd_iter_oprs">Grouped Iterator Operators</a></li>
|
||||
<li><a href="#iterator">Iterator Helpers</a>
|
||||
<ul>
|
||||
<li><a href="#iterator_helpers_notes">Iterator Helper
|
||||
Notes</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#i_demo">Iterator Demonstration and Test
|
||||
Program</a></li>
|
||||
</ul></li>
|
||||
@ -151,6 +162,8 @@ domains, <i>i.e.</i> eventually more useful.</p>
|
||||
|
||||
<h3><a name="two_arg">Two-Argument</a> Template Forms</h3>
|
||||
|
||||
<h4><a name="two_arg_gen">General Considerations</a></h4>
|
||||
|
||||
<p>The arguments to a binary operator commonly have identical types, but
|
||||
it is not unusual to want to define operators which combine different
|
||||
types. For <a href="#example">example</a>, one might want to multiply a
|
||||
@ -176,6 +189,46 @@ trailing <code>'1'</code> are provided for symmetry and to enable
|
||||
certain applications of the <a href="#chaining">base class chaining</a>
|
||||
technique.</p>
|
||||
|
||||
<h4><a name="mixed_arithmetics">Mixed Arithmetics</a></h4>
|
||||
|
||||
<p>Another application of the two-argument template forms is for
|
||||
mixed arithmetics between a type <code>T</code> and a type <code>U</code>
|
||||
that is convertible to <code>T</code>. In this case there are two ways
|
||||
where the two-argument template forms are helpful: one is to provide
|
||||
the respective signatures for operator overloading, the second is
|
||||
performance.</p>
|
||||
|
||||
<p>With respect to the operator overloading assume <i>e.g.</i> that
|
||||
<code>U</code> is <code>int</code>, that <code>T</code> is an user-defined
|
||||
unlimited integer type, and that <code>double operator-(double, const
|
||||
T&)</code> exists. If one wants to compute <code>int - T</code> and
|
||||
does not provide <code>T operator-(int, const T&)</code>, the
|
||||
compiler will consider <code>double operator-(double, const T&)</code>
|
||||
to be a better match than <code>T operator-(const T&, const
|
||||
T&)</code>, which will probably be different from the user's intention.
|
||||
To define a complete set of operator signatures, additional 'left' forms
|
||||
of the two-argument template forms are provided (<code><a
|
||||
href="#subtractable2_left">subtractable2_left<T, U></a></code>,
|
||||
<code><a href="#dividable2_left">dividable2_left<T, U></a></code>,
|
||||
<code><a href="#modable2_left">modable2_left<T, U></a></code>) that
|
||||
define the signatures for non-commutative operators where <code>U</code>
|
||||
appears on the left hand side (<code>operator-(const U&, const
|
||||
T&)</code>, <code>operator/(const U&, const T&)</code>,
|
||||
<code>operator%(const U&, const T&)</code>).</p>
|
||||
|
||||
<p>With respect to the performance observe that when one uses the
|
||||
single type binary operator for mixed type arithmetics, the type
|
||||
<code>U</code> argument has to be converted to type <code>T</code>. In
|
||||
practice, however, there are often more efficient implementations of,
|
||||
say <code>T::operator-=(const U&)</code> that avoid unnecessary
|
||||
conversions from <code>U</code> to <code>T</code>. The two-argument
|
||||
template forms of the arithmetic operator create additional operator
|
||||
interfaces that use these more efficient implementations. There is, however,
|
||||
no performance gain in the 'left' forms: they still need a conversion
|
||||
from <code>U</code> to <code>T</code> and have an implementation
|
||||
equivalent to the code that would be automatically created by the compiler
|
||||
if it considered the single type binary operator to be the best match.</p>
|
||||
|
||||
<h3>Base Class <a name="chaining">Chaining</a> and Object Size</h3>
|
||||
|
||||
<p>Every operator class template, except the <a href="#ex_oprs">arithmetic
|
||||
@ -419,6 +472,12 @@ for the <a href="#chaining">base class chaining</a> technique.
|
||||
<td><code>t -= u</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="subtractable2_left">subtractable2_left<T, U></a></code></td>
|
||||
<td><code>T operator-(const U&, const T&)</code></td>
|
||||
<td><code>T temp(u); temp -= t</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="multipliable1">multipliable<T></a></code><br>
|
||||
<code>multipliable1<T></code></td>
|
||||
@ -448,6 +507,12 @@ for the <a href="#chaining">base class chaining</a> technique.
|
||||
<td><code>t /= u</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="dividable2_left">dividable2_left<T, U></a></code></td>
|
||||
<td><code>T operator/(const U&, const T&)</code></td>
|
||||
<td><code>T temp(u); temp /= t</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="modable1">modable<T></a></code><br>
|
||||
<code>modable1<T></code></td>
|
||||
@ -462,6 +527,12 @@ for the <a href="#chaining">base class chaining</a> technique.
|
||||
<td><code>t %= u</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="modable2_left">modable2_left<T, U></a></code></td>
|
||||
<td><code>T operator%(const U&, const T&)</code></td>
|
||||
<td><code>T temp(u); temp %= t</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="orable1">orable<T></a></code><br>
|
||||
<code>orable1<T></code></td>
|
||||
@ -588,8 +659,9 @@ for the <a href="#chaining">base class chaining</a> technique.
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><strong><a name="ordering">Ordering Note</a></strong><br>
|
||||
The <code><a href="#less_than_comparable1">less_than_comparable<T></a></code>
|
||||
<h4><a name="ordering">Ordering</a> Note</h4>
|
||||
|
||||
<p>The <code><a href="#less_than_comparable1">less_than_comparable<T></a></code>
|
||||
and <code><a href="#partially_ordered1">partially_ordered<T></a></code>
|
||||
templates provide the same set of operations. However, the workings of
|
||||
<code><a href="#less_than_comparable1">less_than_comparable<T></a></code>
|
||||
@ -771,6 +843,109 @@ optional template parameter <code>B</code>, which is not shown, for the
|
||||
<li><code><a href="#right_shiftable2">right_shiftable<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ring_operators1">ring_operators<T></a></code><br>
|
||||
<code>ring_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#additive1">additive<T></a></code></li>
|
||||
<li><code><a href="#multipliable1">multipliable<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ring_operators2">ring_operators<T, U></a></code><br>
|
||||
<code>ring_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#additive2">additive<T, U></a></code></li>
|
||||
<li><code><a href="#subtractable2_left">subtractable2_left<T, U></a></code></li>
|
||||
<li><code><a href="#multipliable2">multipliable<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_ring_operators1">ordered_ring_operators<T></a></code><br>
|
||||
<code>ordered_ring_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators1">ring_operators<T></a></code></li>
|
||||
<li><code><a href="#totally_ordered1">totally_ordered<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_ring_operators2">ordered_ring_operators<T, U></a></code><br>
|
||||
<code>ordered_ring_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators2">ring_operators<T, U></a></code></li>
|
||||
<li><code><a href="#totally_ordered2">totally_ordered<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="field_operators1">field_operators<T></a></code><br>
|
||||
<code>field_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators1">ring_operators<T></a></code></li>
|
||||
<li><code><a href="#dividable1">dividable<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="field_operators2">field_operators<T, U></a></code><br>
|
||||
<code>field_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators2">ring_operators<T, U></a></code></li>
|
||||
<li><code><a href="#dividable2">dividable<T, U></a></code></li>
|
||||
<li><code><a href="#dividable2_left">dividable2_left<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_field_operators1">ordered_field_operators<T></a></code><br>
|
||||
<code>ordered_field_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#field_operators1">field_operators<T></a></code></li>
|
||||
<li><code><a href="#totally_ordered1">totally_ordered<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_field_operators2">ordered_field_operators<T, U></a></code><br>
|
||||
<code>ordered_field_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#field_operators2">field_operators<T, U></a></code></li>
|
||||
<li><code><a href="#totally_ordered2">totally_ordered<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="euclidian_ring_operators1">euclidian_ring_operators<T></a></code><br>
|
||||
<code>euclidian_ring_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators1">ring_operators<T></a></code></li>
|
||||
<li><code><a href="#dividable1">dividable<T></a></code></li>
|
||||
<li><code><a href="#modable1">modable<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="euclidian_ring_operators2">euclidian_ring_operators<T, U></a></code><br>
|
||||
<code>euclidian_ring_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators2">ring_operators<T, U></a></code></li>
|
||||
<li><code><a href="#dividable2">dividable<T, U></a></code></li>
|
||||
<li><code><a href="#dividable2_left">dividable2_left<T, U></a></code></li>
|
||||
<li><code><a href="#modable2">modable<T, U></a></code></li>
|
||||
<li><code><a href="#modable2_left">modable2_left<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_euclidian_ring_operators1">ordered_euclidian_ring_operators<T></a></code><br>
|
||||
<code>ordered_euclidian_ring_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#euclidian_ring_operators1">euclidian_ring_operators<T></a></code></li>
|
||||
<li><code><a href="#totally_ordered1">totally_ordered<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_euclidian_ring_operators2">ordered_euclidian_ring_operators<T, U></a></code><br>
|
||||
<code>ordered_euclidian_ring_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#euclidian_ring_operators2">euclidian_ring_operators<T, U></a></code></li>
|
||||
<li><code><a href="#totally_ordered2">totally_ordered<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<h3><a name="ex_oprs">Example</a> Templates</h3>
|
||||
@ -888,19 +1063,87 @@ href="#chaining">base class chaining</a>.</p>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="iterator">Iterator</a> Helpers</h3>
|
||||
<h3><a name="grpd_iter_oprs">Grouped Iterator Operators</a></h3>
|
||||
|
||||
<p>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 <a
|
||||
href="#chaining">base class chaining</a>. For convenience, the helper
|
||||
classes also fill in all of the typedef's required of iterators by the
|
||||
C++ standard (<code>iterator_category</code>, <code>value_type</code>,
|
||||
<i>etc.</i>).</p>
|
||||
<p>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 <code>B</code>,
|
||||
which is not shown, to support <a href="#chaining">base class chaining</a>.</p>
|
||||
|
||||
<table cellpadding="5" border="1" align="center">
|
||||
<caption>Iterator Helper Template Classes</caption>
|
||||
<caption>Iterator Operator Class Templates</caption>
|
||||
<tr>
|
||||
<td colspan="2"><table align="center" border="1">
|
||||
<caption><em>Key</em></caption>
|
||||
<tr>
|
||||
<td><code>T</code>: operand type</td>
|
||||
<td><code>P</code>: <code>pointer</code> type</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>D</code>: <code>difference_type</code></td>
|
||||
<td><code>R</code>: <code>reference</code> type</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>V</code>: <code>value_type</code></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Template</th>
|
||||
<th>Component Operator Templates</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="input_iteratable">input_iteratable<T, P></a></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#equality_comparable1">equality_comparable<T></a></code></li>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#dereferenceable">dereferenceable<T, P></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="output_iteratable">output_iteratable<T></a></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="forward_iteratable">forward_iteratable<T, P></a></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#input_iteratable">input_iteratable<T, P></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="bidirectional_iteratable">bidirectional_iteratable<T, P></a></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#forward_iteratable">forward_iteratable<T, P></a></code></li>
|
||||
<li><code><a href="#decrementable">decrementable<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="random_access_iteratable">random_access_iteratable<T, P, D, R></a></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#bidirectional_iteratable">bidirectional_iteratable<T, P></a></code></li>
|
||||
<li><code><a href="#totally_ordered1">totally_ordered<T></a></code></li>
|
||||
<li><code><a href="#additive2">additive<T, D></a></code></li>
|
||||
<li><code><a href="#indexable">indexable<T, D, R></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="iterator">Iterator</a> Helpers</h3>
|
||||
|
||||
<p>There are also five iterator helper class templates, each corresponding
|
||||
to a different iterator category. These classes cannot be used for <a
|
||||
href="#chaining">base class chaining</a>. The following summaries
|
||||
show that these class templates supply both the iterator operators from
|
||||
the <a href="#grpd_iter_oprs">iterator operator class templates</a> and
|
||||
the iterator typedef's required by the C++ standard (<code>iterator_category</code>,
|
||||
<code>value_type</code>, <i>etc.</i>).</p>
|
||||
|
||||
<table cellpadding="5" border="1" align="center">
|
||||
<caption>Iterator Helper Class Templates</caption>
|
||||
<tr>
|
||||
<td colspan="2"><table align="center" border="1">
|
||||
<caption><em>Key</em></caption>
|
||||
@ -926,16 +1169,14 @@ C++ standard (<code>iterator_category</code>, <code>value_type</code>,
|
||||
<td><code><a name="input_iterator_helper">input_iterator_helper<T, V, D, P, R></a></code></td>
|
||||
<td>Supports the operations and has the requirements of
|
||||
<ul>
|
||||
<li><code><a href="#equality_comparable1">equality_comparable<T></a></code></li>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#dereferenceable">dereferenceable<T, P></a></code></li>
|
||||
<li><code><a href="#input_iteratable">input_iteratable<T, P></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr valign="baseline">
|
||||
<td><code><a name="output_iterator_helper">output_iterator_helper<T></a></code></td>
|
||||
<td>Supports the operations and has the requirements of
|
||||
<ul>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#output_iteratable">output_iteratable<T></a></code></li>
|
||||
</ul>
|
||||
See also [<a href="#1">1</a>], [<a href="#2">2</a>].
|
||||
</td>
|
||||
@ -944,33 +1185,21 @@ C++ standard (<code>iterator_category</code>, <code>value_type</code>,
|
||||
<td><code><a name="forward_iterator_helper">forward_iterator_helper<T, V, D, P, R></a></code></td>
|
||||
<td>Supports the operations and has the requirements of
|
||||
<ul>
|
||||
<li><code><a href="#equality_comparable1">equality_comparable<T></a></code></li>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#dereferenceable">dereferenceable<T, P></a></code></li>
|
||||
<li><code><a href="#forward_iteratable">forward_iteratable<T, P></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr valign="baseline">
|
||||
<td><code><a name="bidirectional_iterator_helper">bidirectional_iterator_helper<T, V, D, P, R></a></code></td>
|
||||
<td>Supports the operations and has the requirements of
|
||||
<ul>
|
||||
<li><code><a href="#equality_comparable1">equality_comparable<T></a></code></li>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#decrementable">decrementable<T></a></code></li>
|
||||
<li><code><a href="#dereferenceable">dereferenceable<T, P></a></code></li>
|
||||
<li><code><a href="#bidirectional_iteratable">bidirectional_iteratable<T, P></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr valign="baseline">
|
||||
<td><code><a name="random_access_iterator_helper">random_access_iterator_helper<T, V, D, P, R></a></code></td>
|
||||
<td>Supports the operations and has the requirements of
|
||||
<ul>
|
||||
<li><code><a href="#equality_comparable1">equality_comparable<T></a></code></li>
|
||||
<li><code><a href="#less_than_comparable1">less_than_comparable<T></a></code></li>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#decrementable">decrementable<T></a></code></li>
|
||||
<li><code><a href="#dereferenceable">dereferenceable<T, P></a></code></li>
|
||||
<li><code><a href="#addable2">addable<T, D></a></code></li>
|
||||
<li><code><a href="#subtractable2">subtractable<T, D></a></code></li>
|
||||
<li><code><a href="#indexable">indexable<T, D, R></a></code></li>
|
||||
<li><code><a href="#random_access_iteratable">random_access_iteratable<T, P, D, R></a></code></li>
|
||||
</ul>
|
||||
To satisfy <cite><a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a></cite>,
|
||||
<code>x1 - x2</code> with return convertible to <code>D</code>
|
||||
@ -978,7 +1207,7 @@ C++ standard (<code>iterator_category</code>, <code>value_type</code>,
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="iterator_helpers_notes">Iterator Helper Notes</a></h3>
|
||||
<h4><a name="iterator_helpers_notes">Iterator Helper Notes</a></h4>
|
||||
|
||||
<p><a name="1">[1]</a> Unlike other iterator helpers templates,
|
||||
<code>output_iterator_helper</code> takes only one template parameter - the type of
|
||||
@ -987,8 +1216,8 @@ restriction, the standard requires <code>difference_type</code> and
|
||||
<code>value_type</code> of any output iterator to be
|
||||
<code>void</code> (24.3.1 [lib.iterator.traits]), and
|
||||
<code>output_iterator_helper</code> template respects this
|
||||
requirement. Also, output iterators in the standard have void <tt>pointer</tt> and
|
||||
<tt>reference</tt> types, so the <tt>output_iterator_helper</tt> does the
|
||||
requirement. Also, output iterators in the standard have void <code>pointer</code> and
|
||||
<code>reference</code> types, so the <code>output_iterator_helper</code> does the
|
||||
same.
|
||||
|
||||
<p><a name="2">[2]</a> 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.</p>
|
||||
partial ordering, and arithmetic conversions. Added the
|
||||
grouped operator classes. Added helper classes for
|
||||
input and output iterators.
|
||||
|
||||
<dt>Helmut Zeisel
|
||||
<dd>Contributed the 'left' operators and added some
|
||||
grouped operator classes.
|
||||
</dl>
|
||||
|
||||
<h2>Note for Users of <a name="old_lib_note">Older Versions</a></h2>
|
||||
@ -1142,7 +1375,7 @@ the library remain backward-compatible.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised: 25 Jun 2001</p>
|
||||
<p>Revised: 30 Oct 2001</p>
|
||||
|
||||
<p>Copyright © David Abrahams and Beman Dawes 1999-2001.
|
||||
Permission to copy, use, modify, sell and distribute this document is
|
||||
|
@ -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 <class T, class U>
|
||||
T true_value(Wrapped4<T,U> x) { return x.value(); }
|
||||
|
||||
// U must be convertible to T
|
||||
template <class T, class U>
|
||||
class Wrapped5
|
||||
: boost::ordered_field_operators2<Wrapped5<T, U>, U>
|
||||
, boost::ordered_field_operators1<Wrapped5<T, U> >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped5( T v = T() ) : _value(v) {}
|
||||
|
||||
// Conversion from U to Wrapped5<T,U>
|
||||
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 <class T, class U>
|
||||
T true_value(Wrapped5<T,U> x) { return x.value(); }
|
||||
|
||||
// U must be convertible to T
|
||||
template <class T, class U>
|
||||
class Wrapped6
|
||||
: boost::ordered_euclidian_ring_operators2<Wrapped6<T, U>, U>
|
||||
, boost::ordered_euclidian_ring_operators1<Wrapped6<T, U> >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped6( T v = T() ) : _value(v) {}
|
||||
|
||||
// Conversion from U to Wrapped6<T,U>
|
||||
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 <class T, class U>
|
||||
T true_value(Wrapped6<T,U> x) { return x.value(); }
|
||||
|
||||
// MyInt uses only the single template-argument form of all_operators<>
|
||||
typedef Wrapped1<int> MyInt;
|
||||
|
||||
@ -193,6 +263,10 @@ namespace
|
||||
|
||||
typedef Wrapped4<short, short> MyShort;
|
||||
|
||||
typedef Wrapped5<double, int> MyDoubleInt;
|
||||
|
||||
typedef Wrapped6<long, int> MyLongInt;
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
@ -267,6 +341,13 @@ namespace
|
||||
BOOST_TEST( (x1 - y1).value() == (x2 - y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
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 <class X1, class Y1, class X2, class Y2>
|
||||
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
@ -275,6 +356,14 @@ namespace
|
||||
BOOST_TEST( (x1 / y1).value() == (x2 / y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
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 <class X1, class Y1, class X2, class Y2>
|
||||
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
@ -283,6 +372,14 @@ namespace
|
||||
BOOST_TEST( (x1 % y1).value() == (x2 % y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
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 <class X1, class Y1, class X2, class Y2>
|
||||
void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
@ -374,6 +471,14 @@ namespace
|
||||
test_decrementable( x1, x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
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 <class Big, class Small>
|
||||
struct tester
|
||||
{
|
||||
@ -388,6 +493,19 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
template <class Big, class Small>
|
||||
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<Big, Small>(b1), s, b1, s );
|
||||
}
|
||||
};
|
||||
|
||||
// added as a regression test. We had a bug which this uncovered.
|
||||
struct Point
|
||||
: boost::addable<Point
|
||||
@ -427,6 +545,13 @@ template Wrapped2<unsigned int, unsigned char>;
|
||||
template Wrapped2<unsigned long, unsigned int>;
|
||||
template Wrapped2<unsigned long, unsigned char>;
|
||||
template Wrapped2<unsigned long, unsigned long>;
|
||||
|
||||
template Wrapped6<long, int>;
|
||||
template Wrapped6<long, signed char>;
|
||||
template Wrapped6<int, signed char>;
|
||||
template Wrapped6<unsigned long, unsigned int>;
|
||||
template Wrapped6<unsigned long, unsigned char>;
|
||||
template Wrapped6<unsigned int, unsigned char>;
|
||||
#endif
|
||||
|
||||
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
|
||||
@ -459,6 +584,14 @@ test_main( int , char * [] )
|
||||
tester<unsigned long, unsigned long>()(r);
|
||||
tester<unsigned int, unsigned int>()(r);
|
||||
tester<unsigned int, unsigned char>()(r);
|
||||
|
||||
tester_left<long, int>()(r);
|
||||
tester_left<long, signed char>()(r);
|
||||
tester_left<int, signed char>()(r);
|
||||
|
||||
tester_left<unsigned long, unsigned int>()(r);
|
||||
tester_left<unsigned long, unsigned char>()(r);
|
||||
tester_left<unsigned int, unsigned char>()(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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user