From 18944572b7f9544b0106f78423e0d1eb3e3aa349 Mon Sep 17 00:00:00 2001
From: Dave Abrahams
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 example, one might want to multiply a
@@ -176,6 +189,46 @@ trailing '1'
are provided for symmetry and to enable
certain applications of the base class chaining
technique.
Another application of the two-argument template forms is for
+mixed arithmetics between a type T
and a type U
+that is convertible to T
. 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.
With respect to the operator overloading assume e.g. that
+U
is int
, that T
is an user-defined
+unlimited integer type, and that double operator-(double, const
+T&)
exists. If one wants to compute int - T
and
+does not provide T operator-(int, const T&)
, the
+compiler will consider double operator-(double, const T&)
+to be a better match than T operator-(const T&, const
+T&)
, 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 (subtractable2_left<T, U>
,
+dividable2_left<T, U>
,
+modable2_left<T, U>
) that
+define the signatures for non-commutative operators where U
+appears on the left hand side (operator-(const U&, const
+T&)
, operator/(const U&, const T&)
,
+operator%(const U&, const T&)
).
With respect to the performance observe that when one uses the
+single type binary operator for mixed type arithmetics, the type
+U
argument has to be converted to type T
. In
+practice, however, there are often more efficient implementations of,
+say T::operator-=(const U&)
that avoid unnecessary
+conversions from U
to T
. 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 U
to T
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.
Every operator class template, except the arithmetic @@ -419,6 +472,12 @@ for the base class chaining technique.
t -= u
.T
.subtractable2_left<T, U>
T operator-(const U&, const T&)
T temp(u); temp -= t
.T
.multipliable<T>
multipliable1<T>
t /= u
.T
.dividable2_left<T, U>
T operator/(const U&, const T&)
T temp(u); temp /= t
.T
.modable<T>
modable1<T>
t %= u
.T
.modable2_left<T, U>
T operator%(const U&, const T&)
T temp(u); temp %= t
.T
.orable<T>
orable1<T>
Ordering Note
-The less_than_comparable<T>
+
The less_than_comparable<T>
and partially_ordered<T>
templates provide the same set of operations. However, the workings of
less_than_comparable<T>
@@ -771,6 +843,109 @@ optional template parameter B
, which is not shown, for the
right_shiftable<T, U>
ring_operators<T>
ring_operators1<T>
additive<T>
multipliable<T>
ring_operators<T, U>
ring_operators2<T, U>
ordered_ring_operators<T>
ordered_ring_operators1<T>
ordered_ring_operators<T, U>
ordered_ring_operators2<T, U>
field_operators<T>
field_operators1<T>
field_operators<T, U>
field_operators2<T, U>
ordered_field_operators<T>
ordered_field_operators1<T>
ordered_field_operators<T, U>
ordered_field_operators2<T, U>
euclidian_ring_operators<T>
euclidian_ring_operators1<T>
ring_operators<T>
dividable<T>
modable<T>
euclidian_ring_operators<T, U>
euclidian_ring_operators2<T, U>
ordered_euclidian_ring_operators<T>
ordered_euclidian_ring_operators1<T>
ordered_euclidian_ring_operators<T, U>
ordered_euclidian_ring_operators2<T, U>
There are five separate iterator helper classes, each for a
-different category of iterator. Here is a summary of the core set of
-operators that the custom iterator must define, and the extra operators
-that are created by the helper classes. These classes cannot be used for base class chaining. For convenience, the helper
-classes also fill in all of the typedef's required of iterators by the
-C++ standard (iterator_category
, value_type
,
-etc.).
There are five iterator operator class templates, each for a different
+category of iterator. The following table shows the operator groups
+for any category that a custom iterator could define. These class
+templates have an additional optional template parameter B
,
+which is not shown, to support base class chaining.
|
+ |||||||
Template | +Component Operator Templates | +||||||
---|---|---|---|---|---|---|---|
input_iteratable<T, P> |
+ + | ||||||
output_iteratable<T> |
+
|
+ ||||||
forward_iteratable<T, P> |
+ + | ||||||
bidirectional_iteratable<T, P> |
+ + | ||||||
random_access_iteratable<T, P, D, R> |
+ + |
There are also five iterator helper class templates, each corresponding
+to a different iterator category. These classes cannot be used for base class chaining. The following summaries
+show that these class templates supply both the iterator operators from
+the iterator operator class templates and
+the iterator typedef's required by the C++ standard (iterator_category
,
+value_type
, etc.).
Iterator Helper Notes+Iterator Helper Notes[1] Unlike other iterator helpers templates,
[2] As self-proxying is the easiest and most common way to @@ -1008,13 +1237,13 @@ template<class UnaryFunction> struct function_output_iterator : boost::output_iterator_helper< function_output_iterator<UnaryFunction> > { - explicit function_output_iterator(UnaryFunction const& f = UnaryFunction()) + explicit function_output_iterator(UnaryFunction const& f = UnaryFunction()) : func(f) {} template<typename T> - function_output_iterator& operator=(T const& value) + function_output_iterator& operator=(T const& value) { - this->func(value); + this->func(value); return *this; } @@ -1093,6 +1322,10 @@ the test results with selected platforms. partial ordering, and arithmetic conversions. Added the grouped operator classes. Added helper classes for input and output iterators. + +Note for Users of Older Versions@@ -1142,7 +1375,7 @@ the library remain backward-compatible.- Revised: 25 Jun 2001 +Revised: 30 Oct 2001 Copyright © David Abrahams and Beman Dawes 1999-2001.
Permission to copy, use, modify, sell and distribute this document is
diff --git a/operators_test.cpp b/operators_test.cpp
index ce03e87..ac7988d 100644
--- a/operators_test.cpp
+++ b/operators_test.cpp
@@ -8,6 +8,8 @@
// See http://www.boost.org for most recent version including documentation.
// Revision History
+// 01 Oct 01 Added tests for "left" operators
+// and new grouped operators. (Helmut Zeisel)
// 20 May 01 Output progress messages. Added tests for new operator
// templates. Updated random number generator. Changed tests to
// use Boost Test Tools library. (Daryle Walker)
@@ -184,6 +186,74 @@ namespace
template |