mirror of
https://github.com/boostorg/utility.git
synced 2025-05-09 02:44:10 +00:00
2003 lines
54 KiB
Plaintext
2003 lines
54 KiB
Plaintext
[/
|
|
/ Copyright (c) 2012 Marshall Clow
|
|
/ Copyright (c) 2021, Alan Freitas
|
|
/
|
|
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
/]
|
|
|
|
[/===============]
|
|
[#sec:operators]
|
|
[section Operators]
|
|
[/===============]
|
|
|
|
[section Introduction]
|
|
|
|
The header [@../../../include/boost/operators.hpp `<boost/operators.hpp>`] supplies
|
|
several sets of class templates in `namespace boost`. These templates define
|
|
operators at namespace scope in terms of a minimal number of fundamental
|
|
operators provided by the class.
|
|
|
|
[endsect]
|
|
|
|
[#sec:rationale]
|
|
[section Rationale]
|
|
|
|
Overloaded operators for class types typically occur in groups. If you
|
|
can write `x + y`, you probably also want to be able to write `x += y`.
|
|
If you can write `x < y,` you also want `x > y`, `x >= y,` and `x <= y`.
|
|
|
|
Moreover, unless your class has really surprising behavior, some of these
|
|
related operators can be defined in terms of others (e.g. `x >= y`
|
|
is equivalent to `!(x < y)`).
|
|
|
|
Replicating this boilerplate for multiple classes is both tedious and
|
|
error-prone. The [@../../../include/boost/operators.hpp `<boost/operators.hpp>`] templates
|
|
help by generating operators for you at namespace scope based on other
|
|
operators you have defined in your class.
|
|
|
|
If, for example, you declare a class like this:
|
|
|
|
```
|
|
class MyInt
|
|
: boost::__operators__<MyInt>
|
|
{
|
|
bool operator<(const MyInt& x) const;
|
|
bool operator==(const MyInt& x) const;
|
|
MyInt& operator+=(const MyInt& x);
|
|
MyInt& operator-=(const MyInt& x);
|
|
MyInt& operator*=(const MyInt& x);
|
|
MyInt& operator/=(const MyInt& x);
|
|
MyInt& operator%=(const MyInt& x);
|
|
MyInt& operator|=(const MyInt& x);
|
|
MyInt& operator&=(const MyInt& x);
|
|
MyInt& operator^=(const MyInt& x);
|
|
MyInt& operator++();
|
|
MyInt& operator--();
|
|
};
|
|
```
|
|
|
|
then the __operators__<> template adds more than a dozen additional operators, such as
|
|
`operator>`, `operator<=`, `operator>=`, and the binary `operator+`.
|
|
|
|
[link sec:two_arg Two-argument forms] of the templates are also provided to allow interaction with other types.
|
|
|
|
[#sec:semantics]
|
|
This is a ['Summary of Template Semantics]:
|
|
|
|
# Each operator template completes the concept(s) it describes by defining overloaded operators for its target class.
|
|
# The name of an operator class template indicates the [link sec:concepts_note concept] that its target class will model.
|
|
# Usually, the target class uses an instantiation of the operator class template as a base class. Some operator templates support an
|
|
[link sec:explicit_instantiation alternate method].
|
|
# The concept can be compound, i.e. it may represent a common combination of other, simpler concepts.
|
|
# Most operator templates require their target class to support operations related to the operators supplied by
|
|
the template. In accordance with widely accepted [@http://www.gotw.ca/gotw/004.htm coding style recommendations], the
|
|
target class is often required to supply the assignment counterpart operator of the concept's "main operator."
|
|
For example, the `addable` template requires `operator+=(T const&)` and in turn supplies `operator+(T const&, T const&)`.
|
|
|
|
[#sec:concepts_note]
|
|
|
|
['Note on the use of concepts]: The discussed concepts are not necessarily the standard library's
|
|
concepts, such as __CopyConstructible__, although some of them could
|
|
be; they are what we call ['concepts with a small 'c']. In
|
|
particular, they are different from the former ones in that they ['do
|
|
not] describe precise semantics of the operators they require to be
|
|
defined, except the requirements that (a) the semantics of the operators
|
|
grouped in one concept should be consistent (e.g. effects of
|
|
evaluating of `a += b` and `a = a + b` expressions should be the
|
|
same), and (b) that the return types of the operators should follow
|
|
semantics of return types of corresponding operators for built-in types
|
|
(e.g. `operator<` should return a type convertible to `bool`, and
|
|
`T::operator-=` should return type convertible to `T`). Such "loose"
|
|
requirements make `operators` library applicable to broader set of
|
|
target classes from different domains, i.e. eventually more useful.
|
|
|
|
[endsect]
|
|
|
|
[#sec:example]
|
|
[section Example]
|
|
|
|
This example shows how some of the [link sec:arithmetic arithmetic
|
|
operator templates] can be used with a geometric point class
|
|
template.
|
|
|
|
```
|
|
template <class T>
|
|
class point // note: private inheritance is OK here!
|
|
: boost::addable< point<T> // point + point
|
|
, boost::subtractable< point<T> // point - point
|
|
, boost::dividable2< point<T>, T // point / T
|
|
, boost::multipliable2< point<T>, T // point * T, T * point
|
|
> > > >
|
|
{
|
|
public:
|
|
point(T, T);
|
|
T x() const;
|
|
T y() const;
|
|
|
|
point operator+=(const point&);
|
|
// point operator+(point, const point&) automatically
|
|
// generated by addable.
|
|
|
|
point operator-=(const point&);
|
|
// point operator-(point, const point&) automatically
|
|
// generated by subtractable.
|
|
|
|
point operator*=(T);
|
|
// point operator*(point, const T&) and
|
|
// point operator*(const T&, point) auto-generated
|
|
// by multipliable.
|
|
|
|
point operator/=(T);
|
|
// point operator/(point, const T&) auto-generated
|
|
// by dividable.
|
|
private:
|
|
T x_;
|
|
T y_;
|
|
};
|
|
|
|
// now use the point<> class:
|
|
template <class T>
|
|
T length(const point<T> p)
|
|
{
|
|
return sqrt(p.x()*p.x() + p.y()*p.y());
|
|
}
|
|
|
|
const point<float> right(0, 1);
|
|
const point<float> up(1, 0);
|
|
const point<float> pi_over_4 = up + right;
|
|
const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4);
|
|
```
|
|
|
|
[endsect]
|
|
|
|
[#sec:usage]
|
|
[section Usage]
|
|
|
|
[#sec:two_arg]
|
|
[h5 Two-Argument Template Forms]
|
|
|
|
[#sec:two_arg_gen]
|
|
|
|
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 [link sec:example example], one might want to multiply a
|
|
mathematical vector by a scalar. The two-argument template forms of the
|
|
arithmetic operator templates are supplied for this purpose. When
|
|
applying the two-argument form of a template, the desired return type of
|
|
the operators typically determines which of the two types in question
|
|
should be derived from the operator template.
|
|
|
|
For example, if the result of `T + U` is of type `T`, then `T` (not `U`)
|
|
should be derived from [link table:addable2 `addable<T, U>`]. The comparison
|
|
templates [link table:less_than_comparable2 `less_than_comparable<T,U>`],
|
|
[link table:equality_comparable2 `equality_comparable<T, U>`],
|
|
[link table:equivalent2 `equivalent<T, U>`], and
|
|
[link table:partially_ordered2 `partially_ordered<T, U>`] are exceptions to
|
|
this guideline, since the return type of the operators they define is `bool`.
|
|
|
|
On compilers which do not support partial specialization, the
|
|
two-argument forms must be specified by using the names shown below with
|
|
the trailing `'2'`. The single-argument forms with the
|
|
trailing `'1'` are provided for symmetry and to enable certain
|
|
applications of the [link sec:chaining base class chaining]
|
|
technique.
|
|
|
|
[#sec:mixed_arithmetics]
|
|
|
|
['Mixed Arithmetics]: 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
|
|
[link table:subtractable2_left `subtractable2_left<T, U>`],
|
|
[link table:dividable2_left `dividable2_left<T, U>`], and
|
|
[link table:modable2_left `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.
|
|
|
|
[#sec:chaining]
|
|
[h5 Base Class Chaining and Object Size]
|
|
|
|
Every operator class template, except the [link sec:ex_oprs arithmetic examples]
|
|
and the [link sec:iterator iterator helpers], has an additional, but optional,
|
|
template type parameter `B`. This parameter will be a publicly-derived base class of
|
|
the instantiated template. This means it must be a class type. It can be
|
|
used to avoid the bloating of object sizes that is commonly associated
|
|
with multiple-inheritance from several empty base classes. See the
|
|
[link sec:old_lib_note note for users of older versions] for more
|
|
details.
|
|
|
|
To provide support for a group of operators, use the
|
|
`B` parameter to chain operator templates into a single-base
|
|
class hierarchy, demostrated in the [link sec:example usage example].
|
|
The technique is also used by the composite operator templates to group
|
|
operator definitions. If a chain becomes too long for the compiler to
|
|
support, try replacing some of the operator templates with a single
|
|
grouped operator template that chains the old templates together; the
|
|
length limit only applies to the number of templates directly in the
|
|
chain, not those hidden in group templates.
|
|
|
|
['Caveat]: to chain to a base class which is ['not] a Boost operator
|
|
template when using the [link sec:two_arg single-argument form] of a Boost
|
|
operator template, you must specify the operator template with the
|
|
trailing `'1'` in its name. Otherwise the library will assume you mean
|
|
to define a binary operation combining the class you intend to use as
|
|
a base class and the class you're deriving.
|
|
|
|
[#sec:explicit_instantiation]
|
|
[h5 Separate Explicit Instantiation]
|
|
|
|
On some compilers (e.g. Borland, GCC) even single-inheritance
|
|
seems to cause an increase in object size in some cases. If you are not
|
|
defining a class template, you may get better object-size performance by
|
|
avoiding derivation altogether, and instead explicitly instantiating the
|
|
operator template as follows:
|
|
|
|
```
|
|
class my_class // lose the inheritance...
|
|
{
|
|
//...
|
|
};
|
|
|
|
// explicitly instantiate the operators I need.
|
|
template struct less_than_comparable<my_class>;
|
|
template struct equality_comparable<my_class>;
|
|
template struct incrementable<my_class>;
|
|
template struct decrementable<my_class>;
|
|
template struct addable<my_class,long>;
|
|
template struct subtractable<my_class,long>;
|
|
```
|
|
|
|
|
|
|
|
Note that some operator templates cannot use this workaround and must
|
|
be a base class of their primary operand type. Those templates define
|
|
operators which must be member functions, and the workaround needs the
|
|
operators to be independent `friend` functions. The relevant templates
|
|
are:
|
|
|
|
* [link table:dereferenceable `dereferenceable<>`]
|
|
* [link table:indexable `indexable<>`]
|
|
* Any composite operator template that includes at least one of the above
|
|
|
|
As Daniel Krugler pointed out, this technique violates 14.6.5/2 and is thus
|
|
non-portable. The reasoning is, that the operators injected by the instantiation
|
|
of e.g. `less_than_comparable<my_class>` can not be found by ADL according to the
|
|
rules given by 3.4.2/2, since `my_class` is not an associated class of
|
|
`less_than_comparable<my_class>`. Thus only use this technique if all else fails.
|
|
|
|
[#sec:portability]
|
|
[h5 Requirement Portability]
|
|
|
|
Many compilers (e.g. MSVC 6.3, GCC 2.95.2) will not enforce the
|
|
requirements in the operator template tables unless the operations which
|
|
depend on them are actually used. This is not standard-conforming
|
|
behavior. In particular, although it would be convenient to derive all
|
|
your classes which need binary operators from the [link table:operators1 `operators<>`]
|
|
and [link table:operators2 `operators2<>`] templates, regardless of
|
|
whether they implement all the requirements of those templates, this
|
|
shortcut is not portable. Even if this currently works with your
|
|
compiler, it may not work later.
|
|
|
|
[endsect]
|
|
|
|
[#sec:arithmetic]
|
|
[section Arithmetic Operators]
|
|
|
|
The arithmetic operator templates ease the task of creating a custom
|
|
numeric type. Given a core set of operators, the templates add related
|
|
operators to the numeric class. These operations are like the ones the
|
|
standard arithmetic types have, and may include comparisons, adding,
|
|
incrementing, logical and bitwise manipulations, etc. Further,
|
|
since most numeric types need more than one of these operators, some
|
|
templates are provided to combine several of the basic operator templates
|
|
in one declaration.
|
|
|
|
The requirements for the types used to instantiate the simple operator
|
|
templates are specified in terms of expressions which must be valid and
|
|
the expression's return type. The composite operator templates only list
|
|
what other templates they use. The supplied operations and requirements
|
|
of the composite operator templates can be inferred from the operations
|
|
and requirements of the listed components.
|
|
|
|
[#sec:smpl_oprs]
|
|
[h5 Simple Arithmetic Operators]
|
|
|
|
These templates are "simple" since they provide operators based on a
|
|
single operation the base type has to provide. They have an additional
|
|
optional template parameter `B`, which is not shown, for the
|
|
[link sec:chaining base class chaining] technique.
|
|
|
|
The primary operand type `T` needs to be of class type,
|
|
built-in types are not supported.
|
|
|
|
[table Notation
|
|
[[Key] [Description]]
|
|
[[`T`] [primary operand type]]
|
|
[[`t,t1`] [values of type `T`]]
|
|
[[`U`] [alternate operand type]]
|
|
[[`u`] [value of type `U`]]
|
|
]
|
|
|
|
[table Simple Arithmetic Operator Template Classes
|
|
[[Template] [Supplied Operations] [Requirements] [Propagates constexpr]]
|
|
[
|
|
[
|
|
[#table:less_than_comparable1] `less_than_comparable<T>`
|
|
|
|
__less_than_comparable1__`<T>`
|
|
]
|
|
|
|
[
|
|
`bool operator>(const T&, const T&)`
|
|
|
|
`bool operator<=(const T&, const T&)`
|
|
|
|
`bool operator>=(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`t < t1`.
|
|
|
|
Return convertible to `bool`. See the [link sec:ordering Ordering Note]
|
|
]
|
|
|
|
[
|
|
Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:less_than_comparable2]`less_than_comparable<T,U>`
|
|
|
|
__less_than_comparable2__`<T, U>`
|
|
]
|
|
|
|
[
|
|
`bool operator<=(const T&, const U&)`
|
|
|
|
`bool operator>=(const T&, const U&)`
|
|
|
|
`bool operator>(const U&, const T&)`
|
|
|
|
`bool operator<(const U&, const T&)`
|
|
|
|
`bool operator<=(const U&, const T&)`
|
|
|
|
`bool operator>=(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`t < u`. `t > u`.
|
|
|
|
Returns convertible to `bool`. See the [link sec:ordering Ordering Note].
|
|
]
|
|
|
|
[
|
|
Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:equality_comparable1]`equality_comparable<T>`
|
|
|
|
__equality_comparable1__`<T>`
|
|
]
|
|
|
|
[
|
|
`bool operator!=(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`t == t1`.
|
|
|
|
Return convertible to `bool`.
|
|
]
|
|
|
|
[
|
|
Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:equality_comparable2]`equality_comparable<T,U>`
|
|
|
|
__equality_comparable2__`<T, U>`
|
|
]
|
|
|
|
[
|
|
`bool operator==(const U&, const T&)`
|
|
|
|
`bool operator!=(const U&, const T&)`
|
|
|
|
`bool operator!=(const T&, const U&)`
|
|
]
|
|
|
|
[
|
|
`t == u`.
|
|
|
|
Return convertible to `bool`.
|
|
]
|
|
|
|
[
|
|
Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:addable1]`addable<T>`
|
|
|
|
`addable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator+(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp += t1`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:addable2]`addable<T, U>`
|
|
|
|
`addable2<T, U>`
|
|
]
|
|
|
|
[
|
|
`T operator+(const T&, const U&)`
|
|
|
|
`T operator+(const U&, const T& )`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp += u`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:subtractable1]`subtractable<T>`
|
|
|
|
`subtractable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator-(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp -= t1`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:subtractable2]`subtractable<T,U>`
|
|
|
|
`subtractable2<T, U>`
|
|
]
|
|
|
|
[
|
|
`T operator-(const T&, const U&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp -= u`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:subtractable2_left]`subtractable2_left<T,U>`
|
|
]
|
|
|
|
[
|
|
`T operator-(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(u); temp -= t`.
|
|
|
|
Return convertible to `T`.
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:multipliable1]`multipliable<T>`
|
|
|
|
`multipliable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator*(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp *= t1`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:multipliable2]`multipliable<T,U>`
|
|
|
|
`multipliable2<T, U>`
|
|
]
|
|
|
|
[
|
|
`T operator*(const T&, const U&)`
|
|
|
|
`T operator*(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp *= u`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:dividable1]`dividable<T>`
|
|
|
|
`dividable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator/(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp /= t1`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:dividable2]`dividable<T, U>`
|
|
|
|
`dividable2<T, U>`
|
|
]
|
|
|
|
[
|
|
`T operator/(const T&, const U&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp /= u`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:dividable2_left]`dividable2_left<T,U>`
|
|
]
|
|
|
|
[
|
|
`T operator/(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(u); temp /= t`.
|
|
|
|
Return convertible to `T`.
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:modable1]`modable<T>`
|
|
|
|
`modable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator%(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp %= t1`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:modable2]`modable<T, U>`
|
|
|
|
`modable2<T, U>`
|
|
]
|
|
|
|
[
|
|
`T operator%(const T&, const U&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp %= u`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:modable2_left]`modable2_left<T,U>`
|
|
]
|
|
|
|
[
|
|
`T operator%(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(u); temp %= t`.
|
|
|
|
Return convertible to `T`.
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:orable1]`orable<T>`
|
|
|
|
`orable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator|(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp |= t1`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:orable2]`orable<T, U>`
|
|
|
|
`orable2<T, U>`
|
|
]
|
|
|
|
[
|
|
`T operator|(const T&, const U&)`
|
|
|
|
`T operator|(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp |= u`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:andable1]`andable<T>`
|
|
|
|
`andable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator&(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp &= t1`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:andable2]`andable<T, U>`
|
|
|
|
`andable2<T, U>`
|
|
]
|
|
|
|
[
|
|
`T operator&(const T&, const U&)`
|
|
|
|
`T operator&(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp &= u`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:xorable1]`xorable<T>`
|
|
|
|
`xorable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator^(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp ^= t1`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:xorable2]`xorable<T, U>`
|
|
|
|
`xorable2<T, U>`
|
|
]
|
|
|
|
[
|
|
`T operator^(const T&, const U&)`
|
|
|
|
`T operator^(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp ^= u`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:incrementable]`incrementable<T>`
|
|
]
|
|
|
|
[
|
|
`T operator++(T&, int)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); ++t`
|
|
|
|
Return convertible to `T`.
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:decrementable]`decrementable<T>`
|
|
]
|
|
|
|
[
|
|
`T operator--(T&, int)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); --t;`
|
|
|
|
Return convertible to `T`.
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:left_shiftable1]`left_shiftable<T>`
|
|
|
|
`left_shiftable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator<<(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp <<= t1`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:left_shiftable2]`left_shiftable<T,U>`
|
|
|
|
`left_shiftable2<T, U>`
|
|
]
|
|
|
|
[
|
|
`T operator<<(const T&, const U&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp <<= u`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:right_shiftable1]`right_shiftable<T>`
|
|
|
|
`right_shiftable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator>>(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp >>= t1`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:right_shiftable2]`right_shiftable<T,U>`
|
|
|
|
`right_shiftable2<T, U>`
|
|
]
|
|
|
|
[
|
|
`T operator>>(const T&, const U&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp >>= u`.
|
|
|
|
Return convertible to `T`. See the [link sec:symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:equivalent1]`equivalent<T>`
|
|
|
|
__equivalent1__`<T>`
|
|
]
|
|
|
|
[
|
|
`bool operator==(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`t < t1`.
|
|
|
|
Return convertible to `bool`. See the [link sec:ordering Ordering Note].
|
|
]
|
|
|
|
[
|
|
Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:equivalent2]`equivalent<T, U>`
|
|
|
|
__equivalent2__`<T, U>`
|
|
]
|
|
|
|
[
|
|
`bool operator==(const T&, const U&)`
|
|
]
|
|
|
|
[
|
|
`t < u`. `t > u`.
|
|
|
|
Returns convertible to `bool`. See the [link sec:ordering Ordering Note].
|
|
]
|
|
|
|
[
|
|
Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:partially_ordered1]`partially_ordered<T>`
|
|
|
|
__partially_ordered1__`<T>`
|
|
]
|
|
|
|
[
|
|
`bool operator>(const T&, const T&)`
|
|
|
|
`bool operator<=(const T&, const T&)`
|
|
|
|
`bool operator>=(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`t < t1`. `t == t1`.
|
|
|
|
Returns convertible to `bool`. See the [link sec:ordering Ordering Note].
|
|
]
|
|
|
|
[
|
|
Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#table:partially_ordered2]`partially_ordered<T,U>`
|
|
|
|
__partially_ordered2__`<T, U>`
|
|
]
|
|
|
|
[
|
|
`bool operator<=(const T&, const U&)`
|
|
|
|
`bool operator>=(const T&, const U&)`
|
|
|
|
`bool operator>(const U&, const T&)`
|
|
|
|
`bool operator<(const U&, const T&)`
|
|
|
|
`bool operator<=(const U&, const T&)`
|
|
|
|
`bool operator>=(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`t < u`. `t > u`. `t == u`.
|
|
|
|
Returns convertible to `bool`. See the [link sec:ordering Ordering Note].
|
|
]
|
|
|
|
[
|
|
Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22]
|
|
]
|
|
]
|
|
]
|
|
|
|
[#sec:ordering]
|
|
['Ordering Note]: The [link table:less_than_comparable1 `less_than_comparable<T>`] and
|
|
[link table:partially_ordered1 `partially_ordered<T>`] templates provide the same set
|
|
of operations. However, the workings of [link table:less_than_comparable1 `less_than_comparable<T>`] assume
|
|
that all values of type `T` can be placed in a total order. If
|
|
that is not true (e.g. Not-a-Number values in IEEE floating point
|
|
arithmetic), then [link table:partially_ordered1 `partially_ordered<T>`] should be
|
|
used. The [link table:partially_ordered1 `partially_ordered<T>`] template can
|
|
be used for a totally-ordered type, but it is not as efficient as
|
|
[link table:less_than_comparable1 `less_than_comparable<T>`]. This
|
|
rule also applies for [link table:less_than_comparable2 `less_than_comparable<T, U>`] and
|
|
[link table:partially_ordered2 `partially_ordered<T,U>`] with respect to the ordering
|
|
of all `T` and `U` values, and for both versions of
|
|
[link table:equivalent1 `equivalent<>`]. The solution for
|
|
[link table:equivalent1 `equivalent<>`] is to write a custom
|
|
`operator==` for the target class.
|
|
|
|
[#sec:symmetry]
|
|
['Symmetry Note]: Before talking about symmetry, we need to talk about optimizations to
|
|
understand the reasons for the different implementation styles of
|
|
operators. Let's have a look at `operator+` for a class
|
|
`T` as an example:
|
|
|
|
```
|
|
T operator+( const T& lhs, const T& rhs )
|
|
{
|
|
return T( lhs ) += rhs;
|
|
}
|
|
```
|
|
|
|
This would be a normal implementation of `operator+`, but it
|
|
is not an efficient one. An unnamed local copy of `lhs` is
|
|
created, `operator+=` is called on it and it is copied to the
|
|
function return value (which is another unnamed object of type
|
|
`T`). The standard doesn't generally allow the intermediate
|
|
object to be optimized away:
|
|
|
|
["3.7.2/2: Automatic storage duration: If a named automatic object has initialization or a destructor with
|
|
side effects, it shall not be destroyed before the end of its block,
|
|
nor shall it be eliminated as an optimization even if it appears to be
|
|
unused, except that a class object or its copy may be eliminated as
|
|
specified in 12.8.]
|
|
|
|
The reference to 12.8 is important for us:
|
|
|
|
["12.8/15: Copying class objects: (...) For a function with a class return type, if the expression in the
|
|
return statement is the name of a local object, and the cv-unqualified
|
|
type of the local object is the same as the function return type, an
|
|
implementation is permitted to omit creating the temporary object to
|
|
hold the function return value, even if the class copy constructor or
|
|
destructor has side effects.]
|
|
|
|
This optimization is known as the named return value optimization (NRVO),
|
|
which leads us to the following implementation for `operator+`:
|
|
|
|
```
|
|
T operator+( const T& lhs, const T& rhs )
|
|
{
|
|
T nrv( lhs );
|
|
nrv += rhs;
|
|
return nrv;
|
|
}
|
|
```
|
|
|
|
Given this implementation, the compiler is allowed to remove the
|
|
intermediate object. Sadly, not all compilers implement the NRVO, some
|
|
even implement it in an incorrect way which makes it useless here.
|
|
Without the NRVO, the NRVO-friendly code is no worse than the original
|
|
code showed above, but there is another possible implementation, which
|
|
has some very special properties:
|
|
|
|
```
|
|
T operator+( T lhs, const T& rhs )
|
|
{
|
|
return lhs += rhs;
|
|
}
|
|
```
|
|
|
|
The difference to the first implementation is that `lhs` is
|
|
not taken as a constant reference used to create a copy; instead,
|
|
`lhs` is a by-value parameter, thus it is already the copy
|
|
needed. This allows another optimization (12.2/2) for some cases.
|
|
|
|
Consider `a + b + c` where the result of `a + b` is not copied when
|
|
used as `lhs` when adding `c`. This is more efficient than the original
|
|
code, but not as efficient as a compiler using the NRVO. For most people,
|
|
it is still preferable for compilers that don't implement the NRVO, but
|
|
the `operator+` now has a different function signature. Also,
|
|
the number of objects created differs for `(a + b ) + c` and `a + ( b + c )`.
|
|
|
|
Most probably, this won't be a problem for you, but if your code relies on the function
|
|
signature or a strict symmetric behaviour, you should set
|
|
`BOOST_FORCE_SYMMETRIC_OPERATORS` in your user-config. This
|
|
will force the NRVO-friendly implementation to be used even for compilers
|
|
that do not implement the NRVO.
|
|
|
|
[#sec:grpd_oprs]
|
|
[h5 Grouped Arithmetic Operators]
|
|
|
|
The following templates provide common groups of related operations.
|
|
For example, since a type which is addable is usually also subtractable,
|
|
the [link table:additive1 `additive`] template provides the
|
|
combined operators of both. The grouped operator templates have an
|
|
additional optional template parameter `B`, which is not
|
|
shown, for the [link sec:chaining base class chaining] technique.
|
|
|
|
[table Notation
|
|
[[Key] [Description]]
|
|
[[`T`] [primary operand type]]
|
|
[[`U`] [alternate operand type]]
|
|
]
|
|
|
|
[table Grouped Arithmetic Operator Template Classes
|
|
[
|
|
[Template]
|
|
|
|
[Component Operator Templates]
|
|
]
|
|
[
|
|
[
|
|
[#table:totally_ordered1] `totally_ordered<T>`
|
|
|
|
__totally_ordered1__`<T>`
|
|
]
|
|
[
|
|
[link table:less_than_comparable1 `less_than_comparable<T>`]
|
|
|
|
[link table:equality_comparable1 `equality_comparable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:totally_ordered2]`totally_ordered<T,U>`
|
|
|
|
__totally_ordered2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:less_than_comparable2 `less_than_comparable<T,U>`]
|
|
|
|
[link table:equality_comparable2 `equality_comparable<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:additive1]`additive<T>`
|
|
|
|
__additive1__`<T>`
|
|
]
|
|
[
|
|
[link table:addable1 `addable<T>`]
|
|
|
|
[link table:subtractable1 `subtractable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:additive2]`additive<T, U>`
|
|
|
|
__additive2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:addable2 `addable<T, U>`]
|
|
|
|
[link table:subtractable2 `subtractable<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:multiplicative1] `multiplicative<T>`
|
|
|
|
__multiplicative1__`<T>`
|
|
]
|
|
[
|
|
[link table:multipliable1 `multipliable<T>`]
|
|
|
|
[link table:dividable1 `dividable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:multiplicative2]`multiplicative<T,U>`
|
|
|
|
__multiplicative2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:multipliable2 `multipliable<T,U>`]
|
|
|
|
[link table:dividable2 `dividable<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:integer_multiplicative1] `integer_multiplicative<T>`
|
|
|
|
__integer_multiplicative1__`<T>`
|
|
]
|
|
[
|
|
[link table:multiplicative1 `multiplicative<T>`]
|
|
|
|
[link table:modable1 `modable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:integer_multiplicative2] `integer_multiplicative<T,U>`
|
|
|
|
__integer_multiplicative2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:multiplicative2 `multiplicative<T,U>`]
|
|
|
|
[link table:modable2 `modable<T, U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:arithmetic1]`arithmetic<T>`
|
|
|
|
__arithmetic1__`<T>`
|
|
]
|
|
[
|
|
[link table:additive1 `additive<T>`]
|
|
|
|
[link table:multiplicative1 `multiplicative<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:arithmetic2]`arithmetic<T, U>`
|
|
|
|
__arithmetic2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:additive2 `additive<T,U>`]
|
|
|
|
[link table:multiplicative2 `multiplicative<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:integer_arithmetic1] `integer_arithmetic<T>`
|
|
|
|
__integer_arithmetic1__`<T>`
|
|
]
|
|
[
|
|
[link table:additive1 `additive<T>`]
|
|
|
|
[link table:integer_multiplicative1 `integer_multiplicative<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:integer_arithmetic2]`integer_arithmetic<T, U>`
|
|
|
|
__integer_arithmetic2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:additive2 `additive<T,U>`]
|
|
|
|
[link table:integer_multiplicative2 `integer_multiplicative<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:bitwise1]`bitwise<T>`
|
|
|
|
__bitwise1__`<T>`
|
|
]
|
|
[
|
|
[link table:xorable1 `xorable<T>`]
|
|
|
|
[link table:andable1 `andable<T>`]
|
|
|
|
[link table:orable1 `orable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:bitwise2]`bitwise<T, U>`
|
|
|
|
__bitwise2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:xorable2 `xorable<T, U>`]
|
|
|
|
[link table:andable2 `andable<T, U>`]
|
|
|
|
[link table:orable2 `orable<T, U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:unit_steppable] `unit_steppable<T>`
|
|
]
|
|
[
|
|
[link table:incrementable `incrementable<T>`]
|
|
|
|
[link table:decrementable `decrementable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:shiftable1]`shiftable<T>`
|
|
|
|
__shiftable1__`<T>`
|
|
]
|
|
[
|
|
[link table:left_shiftable1 `left_shiftable<T>`]
|
|
|
|
[link table:right_shiftable1 `right_shiftable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:shiftable2]`shiftable<T, U>`
|
|
|
|
__shiftable2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:left_shiftable2 `left_shiftable<T,U>`]
|
|
|
|
[link table:right_shiftable2 `right_shiftable<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:ring_operators1] `ring_operators<T>`
|
|
|
|
__ring_operators1__`<T>`
|
|
]
|
|
[
|
|
[link table:additive1 `additive<T>`]
|
|
|
|
[link table:multipliable1 `multipliable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:ring_operators2]`ring_operators<T,U>`
|
|
|
|
__ring_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:additive2 `additive<T,U>`]
|
|
|
|
[link table:subtractable2_left `subtractable2_left<T,U>`]
|
|
|
|
[link table:multipliable2 `multipliable<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:ordered_ring_operators1] `ordered_ring_operators<T>`
|
|
|
|
__ordered_ring_operators1__`<T>`
|
|
]
|
|
[
|
|
[link table:ring_operators1 `ring_operators<T>`]
|
|
|
|
[link table:totally_ordered1 `totally_ordered<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:ordered_ring_operators2] `ordered_ring_operators<T,U>`
|
|
|
|
__ordered_ring_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:ring_operators2 `ring_operators<T,U>`]
|
|
|
|
[link table:totally_ordered2 `totally_ordered<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:field_operators1]`field_operators<T>`
|
|
|
|
__field_operators1__`<T>`
|
|
]
|
|
[
|
|
[link table:ring_operators1 `ring_operators<T>`]
|
|
|
|
[link table:dividable1 `dividable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:field_operators2]`field_operators<T,U>`
|
|
|
|
__field_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:ring_operators2 `ring_operators<T,U>`]
|
|
|
|
[link table:dividable2 `dividable<T,U>`]
|
|
|
|
[link table:dividable2_left `dividable2_left<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:ordered_field_operators1]`ordered_field_operators<T>`
|
|
|
|
__ordered_field_operators1__`<T>`
|
|
]
|
|
[
|
|
[link table:field_operators1 `field_operators<T>`]
|
|
|
|
[link table:totally_ordered1 `totally_ordered<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:ordered_field_operators2]`ordered_field_operators<T,U>`
|
|
|
|
__ordered_field_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:field_operators2 `field_operators<T,U>`]
|
|
|
|
[link table:totally_ordered2 `totally_ordered<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:euclidean_ring_operators1]`euclidean_ring_operators<T>`
|
|
|
|
__euclidean_ring_operators1__`<T>`
|
|
]
|
|
[
|
|
[link table:ring_operators1 `ring_operators<T>`]
|
|
|
|
[link table:dividable1 `dividable<T>`]
|
|
|
|
[link table:modable1 `modable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:euclidean_ring_operators2] `euclidean_ring_operators<T,U>`
|
|
|
|
__euclidean_ring_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:ring_operators2 `ring_operators<T,U>`]
|
|
|
|
[link table:dividable2 `dividable<T,U>`]
|
|
|
|
[link table:dividable2_left `dividable2_left<T,U>`]
|
|
|
|
[link table:modable2 `modable<T, U>`]
|
|
|
|
[link table:modable2_left `modable2_left<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:ordered_euclidean_ring_operators1] `ordered_euclidean_ring_operators<T>`
|
|
|
|
__ordered_euclidean_ring_operators1__`<T>`
|
|
]
|
|
[
|
|
[link table:euclidean_ring_operators1 `euclidean_ring_operators<T>`]
|
|
|
|
[link table:totally_ordered1 `totally_ordered<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:ordered_euclidean_ring_operators2]`ordered_euclidean_ring_operators<T,U>`
|
|
|
|
__ordered_euclidean_ring_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:euclidean_ring_operators2 `euclidean_ring_operators<T,U>`]
|
|
|
|
[link table:totally_ordered2 `totally_ordered<T,U>`]
|
|
]
|
|
]
|
|
]
|
|
|
|
['Spelling: euclidean vs. euclidian]: Older versions of the
|
|
Boost.Operators library used "`euclidian`", but it was pointed out that
|
|
"`euclidean`" is the more common spelling. To be compatible with older
|
|
version, the library now supports both spellings.
|
|
|
|
[#sec:ex_oprs]
|
|
[h5 Example Templates]
|
|
|
|
The arithmetic operator class templates [link table:operators1 `operators<>`] and
|
|
[link table:operators2 `operators2<>`] are examples of non-extensible operator
|
|
grouping classes. These legacy class templates, from previous versions
|
|
of the header, cannot be used for [link sec:chaining base class chaining].
|
|
|
|
[table Notation
|
|
[[Key] [Description]]
|
|
[[`T`] [primary operand type]]
|
|
[[`U`] [alternate operand type]]
|
|
]
|
|
|
|
[table Final Arithmetic Operator Template Classes
|
|
[
|
|
[Template]
|
|
|
|
[Component Operator Templates]
|
|
]
|
|
[
|
|
[
|
|
[#table:operators1]__operators__`<T>`
|
|
]
|
|
[
|
|
[link table:totally_ordered1 `totally_ordered<T>`]
|
|
|
|
[link table:integer_arithmetic1 `integer_arithmetic<T>`]
|
|
|
|
[link table:bitwise1 `bitwise<T>`]
|
|
|
|
[link table:unit_steppable `unit_steppable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:operators2]__operators__`<T, U>`
|
|
|
|
__operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link table:totally_ordered2 `totally_ordered<T,U>`]
|
|
|
|
[link table:integer_arithmetic2 `integer_arithmetic<T,U>`]
|
|
|
|
[link table:bitwise2 `bitwise<T, U>`]
|
|
]
|
|
]
|
|
]
|
|
|
|
[#sec:a_demo]
|
|
['Arithmetic Operators Demonstration and Test Program]: The
|
|
[@../../../test/operators_test.cpp `operators_test.cpp`]
|
|
program demonstrates the use of the arithmetic operator templates, and
|
|
can also be used to verify correct operation. Check the compiler status
|
|
report for the test results with selected platforms.
|
|
|
|
[endsect]
|
|
|
|
[#sec:deref]
|
|
[section Dereference Operators and Iterator Helpers]
|
|
|
|
The [link sec:iterator iterator helper] templates ease the task of
|
|
creating a custom iterator. Similar to arithmetic types, a complete
|
|
iterator has many operators that are "redundant" and can be implemented
|
|
in terms of the core set of operators.
|
|
|
|
The [link sec:dereference dereference operators] were motivated by
|
|
the [link sec:iterator iterator helpers], but are often useful in
|
|
non-iterator contexts as well. Many of the redundant iterator operators
|
|
are also arithmetic operators, so the iterator helper classes borrow many
|
|
of the operators defined above. In fact, only two new operators need to
|
|
be defined: the pointer-to-member `operator->` and the
|
|
subscript `operator[]`.
|
|
|
|
The requirements for the types used to instantiate the dereference
|
|
operators are specified in terms of expressions which must be valid and
|
|
their return type. The composite operator templates list their component
|
|
templates, which the instantiating type must support, and possibly other
|
|
requirements.
|
|
|
|
[#sec:dereference]
|
|
[h5 Dereference Operators]
|
|
|
|
All the dereference operator templates in this table accept an
|
|
optional template parameter (not shown) to be used for
|
|
[link sec:chaining base class chaining].
|
|
|
|
[table Notation
|
|
[[Key] [Description]]
|
|
[[`T`] [operand type]]
|
|
[[`D`] [`difference_type`]]
|
|
[[`i`] [object of type `T` (an iterator)]]
|
|
[[`P`] [`pointer` type]]
|
|
[[`R`] [`reference` type]]
|
|
[[`n`] [object of type `D` (an index)]]
|
|
]
|
|
|
|
[table Dereference Operator Template Classes
|
|
[
|
|
[Template]
|
|
|
|
[Supplied Operations]
|
|
|
|
[Requirements]
|
|
]
|
|
[
|
|
[
|
|
[#table:dereferenceable]__dereferenceable__`<T,P>`
|
|
]
|
|
[
|
|
`P operator->() const`
|
|
]
|
|
[
|
|
`*i`. Address of the returned value convertible to `P`.
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:indexable]__indexable__`<T, D, R>`
|
|
]
|
|
[
|
|
`R operator[](D n) const`
|
|
]
|
|
[
|
|
`*(i + n)`. Return of type `R`.
|
|
]
|
|
]
|
|
]
|
|
|
|
[#sec:grpd_iter_oprs]
|
|
[h5 Grouped Iterator Operators]
|
|
|
|
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 [link sec:chaining base class chaining].
|
|
|
|
[table Notation
|
|
[[Key] [Description]]
|
|
[[`T`] [operand type]]
|
|
[[`D`] [`difference_type`]]
|
|
[[`V`] [`value_type`]]
|
|
[[`P`] [`pointer` type]]
|
|
[[`R`] [`reference` type]]
|
|
]
|
|
|
|
[table Iterator Operator Class Templates
|
|
[
|
|
[Template]
|
|
|
|
[Component Operator Templates]
|
|
]
|
|
[
|
|
[
|
|
[#table:input_iteratable]__input_iteratable__`<T, P>`
|
|
]
|
|
[
|
|
[link table:equality_comparable1 `equality_comparable<T>`]
|
|
|
|
[link table:incrementable `incrementable<T>`]
|
|
|
|
[link table:dereferenceable `dereferenceable<T,P>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:output_iteratable]__output_iteratable__`<T>`
|
|
]
|
|
[
|
|
[link table:incrementable `incrementable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:forward_iteratable]__forward_iteratable__`<T, P>`
|
|
]
|
|
[
|
|
[link table:input_iteratable `input_iteratable<T,P>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:bidirectional_iteratable] __bidirectional_iteratable__`<T,P>`
|
|
]
|
|
[
|
|
[link table:forward_iteratable `forward_iteratable<T, P>`]
|
|
|
|
[link table:decrementable `decrementable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:random_access_iteratable] __random_access_iteratable__`<T, P, D, R>`
|
|
]
|
|
[
|
|
[link table:bidirectional_iteratable `bidirectional_iteratable<T, P>`]
|
|
|
|
[link table:totally_ordered1 `totally_ordered<T>`]
|
|
|
|
[link table:additive2 `additive<T, D>`]
|
|
|
|
[link table:indexable `indexable<T, D, R>`]
|
|
]
|
|
]
|
|
]
|
|
|
|
[#sec:iterator]
|
|
[h5 Iterator Helpers]
|
|
|
|
There are also five iterator helper class templates, each
|
|
corresponding to a different iterator category. These classes cannot be
|
|
used for [link sec:chaining base class chaining]. The following
|
|
summaries show that these class templates supply both the iterator
|
|
operators from the [link sec:grpd_iter_oprs iterator operator class
|
|
templates] and the iterator `typedef`s required by the C++ standard,
|
|
such as `iterator_category` and `value_type`.
|
|
|
|
[table Notation
|
|
[[Key] [Description]]
|
|
[[`T`] [operand type]]
|
|
[[`D`] [`difference_type`]]
|
|
[[`V`] [`value_type`]]
|
|
[[`P`] [`pointer` type]]
|
|
[[`R`] [`reference` type]]
|
|
[[`x1`, `x2`] [objects of type `T`]]
|
|
]
|
|
|
|
[table Helper Class Templates
|
|
[
|
|
[Template]
|
|
|
|
[Operations and Requirements]
|
|
]
|
|
[
|
|
[
|
|
[#table:input_iterator_helper]__input_iterator_helper__`<T, V, D, P, R>`
|
|
]
|
|
[
|
|
Supports the operations and has the requirements of [link table:input_iteratable `input_iteratable<T, P>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:output_iterator_helper]__output_iterator_helper__`<T>`
|
|
]
|
|
[
|
|
Supports the operations and has the requirements of [link table:output_iteratable `output_iteratable<T>`]
|
|
|
|
See also \[[link note:1 1]\], \[[link note:2 2]\].
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:forward_iterator_helper] __forward_iterator_helper__`<T, V, D, P, R>`
|
|
]
|
|
[
|
|
Supports the operations and has the requirements of [link table:forward_iteratable `forward_iteratable<T, P>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:bidirectional_iterator_helper] __bidirectional_iterator_helper__`<T, V, D, P, R>`
|
|
]
|
|
[
|
|
Supports the operations and has the requirements of [link table:bidirectional_iteratable `bidirectional_iteratable<T, P>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#table:random_access_iterator_helper]__random_access_iterator_helper__`<T, V, D, P, R>`
|
|
]
|
|
[
|
|
Supports the operations and has the requirements of [link table:random_access_iteratable `random_access_iteratable<T, P, D, R>`]
|
|
|
|
To satisfy __RandomAccessIterator__, `x1 - x2` with return convertible to `D` is also required.
|
|
]
|
|
]
|
|
]
|
|
|
|
[#sec:iterator_helpers_notes]
|
|
|
|
['Iterator Helper Notes]:
|
|
|
|
# [#note:1] Unlike other iterator helpers templates, __output_iterator_helper__ takes only one template parameter -
|
|
the type of its target class. Although to some it might seem like an unnecessary restriction, the standard requires
|
|
`difference_type` and `value_type` of any output iterator to be `void` (24.3.1 [lib.iterator.traits]), and
|
|
__output_iterator_helper__ template respects this requirement. Also, output iterators in the standard have void `pointer` and
|
|
`reference` types, so the __output_iterator_helper__ does the same.
|
|
# [#note:2] As self-proxying is the easiest and most common way to implement output iterators (see,
|
|
for example, insert [24.4.2] and stream iterators [24.5] in the standard library),
|
|
__output_iterator_helper__ supports the idiom by defining `operator*` and `operator++` member functions which
|
|
just return a non-const reference to the iterator itself. Support for self-proxying allows us, in many cases,
|
|
to reduce the task of writing an output iterator to writing just two member functions - an appropriate
|
|
constructor and a copy-assignment operator. For example, here is a possible implementation of
|
|
[@boost:/doc/html/iterator/doc/function_output_iterator.html `boost::function_output_iterator`] adaptor:
|
|
|
|
```
|
|
template<class UnaryFunction>
|
|
struct function_output_iterator
|
|
: boost::__output_iterator_helper__< function_output_iterator<UnaryFunction> >
|
|
{
|
|
explicit function_output_iterator(UnaryFunction const& f = UnaryFunction())
|
|
: func(f) {}
|
|
|
|
template<typename T>
|
|
function_output_iterator& operator=(T const& value)
|
|
{
|
|
this->func(value);
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
UnaryFunction func;
|
|
};
|
|
```
|
|
|
|
Note that support for self-proxying does not prevent you from using
|
|
__output_iterator_helper__ to ease any other, different kind of
|
|
output iterator's implementation. If
|
|
__output_iterator_helper__'s target type provides its own
|
|
definition of `operator*` or/and `operator++`, then
|
|
these operators will get used and the ones supplied by
|
|
__output_iterator_helper__ will never be instantiated.
|
|
|
|
[#sec:i_demo]
|
|
[h5 Iterator Demonstration and Test Program]
|
|
|
|
The [@../../../test/iterators_test.cpp `iterators_test.cpp`]
|
|
program demonstrates the use of the iterator templates, and can also be
|
|
used to verify correct operation. The following is the custom iterator
|
|
defined in the test program. It demonstrates a correct (though trivial)
|
|
implementation of the core operations that must be defined in order for
|
|
the iterator helpers to "fill in" the rest of the iterator
|
|
operations.
|
|
|
|
```
|
|
template <class T, class R, class P>
|
|
struct test_iter
|
|
: public boost::__random_access_iterator_helper__<
|
|
test_iter<T, R, P>, T, __std_ptrdiff_t__, P, R
|
|
>
|
|
{
|
|
typedef test_iter self;
|
|
typedef R Reference;
|
|
typedef __std_ptrdiff_t__ Distance;
|
|
|
|
public:
|
|
explicit test_iter(T* i =0);
|
|
test_iter(const self& x);
|
|
self& operator=(const self& x);
|
|
Reference operator*() const;
|
|
self& operator++();
|
|
self& operator--();
|
|
self& operator+=(Distance n);
|
|
self& operator-=(Distance n);
|
|
bool operator==(const self& x) const;
|
|
bool operator<(const self& x) const;
|
|
friend Distance operator-(const self& x, const self& y);
|
|
};
|
|
```
|
|
|
|
Check the [@http://www.boost.org/development/testing.html compiler status report] for the
|
|
test results with selected platforms.
|
|
|
|
[endsect]
|
|
|
|
[#sec:old_lib_note]
|
|
[section Note for Users of Older Versions]
|
|
|
|
The [link sec:chaining changes in the library interface and
|
|
recommended usage] were motivated by some practical issues described
|
|
below. The new version of the library is still backward-compatible with
|
|
the former one, so you are not ['forced] to change any existing code,
|
|
but the old usage is deprecated.
|
|
|
|
Though it was arguably simpler and more intuitive than using
|
|
[link sec:chaining base class chaining], it has been discovered
|
|
that the old practice of deriving from multiple operator
|
|
templates can cause the resulting classes to be much larger than they
|
|
should be. Most modern C++ compilers significantly bloat the size of
|
|
classes derived from multiple empty base classes, even though the base
|
|
classes themselves have no state. For instance, the size of
|
|
`point<int>` from the [link sec:example example]
|
|
above was 12-24 bytes on various compilers for the Win32 platform,
|
|
instead of the expected 8 bytes.
|
|
|
|
Strictly speaking, it was not the library's fault -- the language rules
|
|
allow the compiler to apply the empty base class optimization in that
|
|
situation. In principle an arbitrary number of empty base classes can be
|
|
allocated at the same offset, provided that none of them have a common
|
|
ancestor (see section 10.5 [class.derived] paragraph 5 of the standard).
|
|
|
|
But the language definition also does not ['require] implementations
|
|
to do the optimization, and few if any of today's compilers implement it
|
|
when multiple inheritance is involved. What's worse, it is very unlikely
|
|
that implementors will adopt it as a future enhancement to existing
|
|
compilers, because it would break binary compatibility between code
|
|
generated by two different versions of the same compiler. As Matt Austern
|
|
said, "One of the few times when you have the freedom to do this sort of
|
|
thing is when you are targeting a new architecture...". On the other hand,
|
|
many common compilers will use the empty base optimization for single
|
|
inheritance hierarchies.
|
|
|
|
Given the importance of the issue for the users of the library (which
|
|
aims to be useful for writing light-weight classes like
|
|
`MyInt` or `point<>`), and the forces described above, we decided to change
|
|
the library interface so that the object size bloat could be eliminated even
|
|
on compilers that support only the simplest form of the empty base class
|
|
optimization. The current library interface is the result of those changes.
|
|
Though the new usage is a bit more complicated than the old one, we think
|
|
it's worth it to make the library more useful in real world. Alexy Gurtovoy
|
|
contributed the code which supports the new usage idiom while allowing the
|
|
library to remain backward-compatible.
|
|
|
|
[endsect]
|
|
|
|
[#sec:contributors]
|
|
[section Acknowledgments]
|
|
|
|
* [@http://www.boost.org/people/dave_abrahams.htm Dave Abrahams]:
|
|
Started the library and contributed the arithmetic operators in
|
|
[@../../../include/boost/operators.hpp `boost/operators.hpp`].
|
|
|
|
* [@http://www.boost.org/people/jeremy_siek.htm Jeremy Siek]:
|
|
Contributed the [link sec:deref dereference operators and iterator
|
|
helpers] in [@../../../include/boost/operators.hpp boost/operators.hpp].
|
|
Also contributed [@../../../test/iterators_test.cpp iterators_test.cpp].
|
|
|
|
* [@http://www.boost.org/people/aleksey_gurtovoy.htm Aleksey Gurtovoy]:
|
|
Contributed the code to support [link sec:chaining base class
|
|
chaining] while remaining backward-compatible with old versions of
|
|
the library.
|
|
|
|
* [@http://www.boost.org/people/beman_dawes.html Beman Dawes]:
|
|
Contributed [@../../../test/operators_test.cpp `operators_test.cpp`].
|
|
|
|
* [@http://www.boost.org/people/daryle_walker.html Daryle Walker]:
|
|
Contributed classes for the shift operators, equivalence, partial
|
|
ordering, and arithmetic conversions. Added the grouped operator
|
|
classes. Added helper classes for input and output iterators.
|
|
|
|
* Helmut Zeisel: Contributed the 'left' operators and added some grouped operator
|
|
classes.
|
|
|
|
* Daniel Frey: Contributed the NRVO-friendly and symmetric implementation of
|
|
arithmetic operators.
|
|
|
|
[endsect]
|
|
|
|
[endsect]
|