mirror of
https://github.com/boostorg/utility.git
synced 2025-05-08 18:34:02 +00:00
Since BoostBook stylesheets were updated to pass through Doxygen anchor names to BoostBook output, references from QuickBook and manually written BoostBook docs were broken. Fix this by using classref/classname and similar tools to reference Doxygen-generated content. Also, to avoid anchor clashes between different parts of Boost.Utility docs, use proper anchor namespacing: avoid using manual anchors where possible and use fully qualified namespace where not. Fixes https://github.com/boostorg/utility/issues/110.
2005 lines
65 KiB
Plaintext
2005 lines
65 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)
|
|
/]
|
|
|
|
[/===============]
|
|
[section:operators Operators]
|
|
[/===============]
|
|
|
|
[section Introduction]
|
|
|
|
The header [@../../../../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]
|
|
|
|
[section:rationale 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 [@../../../../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 utility.utilities.operators.usage.two_arg Two-argument forms] of the templates are also provided to allow interaction with other types.
|
|
|
|
[#utility.utilities.operators.rationale.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 utility.utilities.operators.rationale.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 utility.utilities.operators.usage.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&)`.
|
|
|
|
[#utility.utilities.operators.rationale.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]
|
|
|
|
[section:example Example]
|
|
|
|
This example shows how some of the [link utility.utilities.operators.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]
|
|
|
|
[section:usage Usage]
|
|
|
|
[section:two_arg Two-Argument Template Forms]
|
|
|
|
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 utility.utilities.operators.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 utility.utilities.operators.arithmetic.smpl_oprs.addable2 `addable<T, U>`]. The comparison
|
|
templates [link utility.utilities.operators.arithmetic.smpl_oprs.less_than_comparable2 `less_than_comparable<T,U>`],
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.equality_comparable2 `equality_comparable<T, U>`],
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.equivalent2 `equivalent<T, U>`], and
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.usage.chaining base class chaining]
|
|
technique.
|
|
|
|
[#utility.utilities.operators.usage.two_arg.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 utility.utilities.operators.arithmetic.smpl_oprs.subtractable2_left `subtractable2_left<T, U>`],
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.dividable2_left `dividable2_left<T, U>`], and
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.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.
|
|
|
|
[endsect]
|
|
|
|
[section:chaining Base Class Chaining and Object Size]
|
|
|
|
Every operator class template, except the [link utility.utilities.operators.arithmetic.ex_oprs arithmetic examples]
|
|
and the [link utility.utilities.operators.deref.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 utility.utilities.operators.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 utility.utilities.operators.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 utility.utilities.operators.usage.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.
|
|
|
|
[endsect]
|
|
|
|
[section:explicit_instantiation 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 utility.utilities.operators.deref.dereference.dereferenceable `dereferenceable<>`]
|
|
* [link utility.utilities.operators.deref.dereference.indexable `indexable<>`]
|
|
* Any composite operator template that includes at least one of the above
|
|
|
|
As Daniel Krugler pointed out, this technique violates C++11 [sect]14.6.5/2 \[temp.inject\]
|
|
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 C++11 [sect]3.4.2/2 \[basic.lookup.argdep\], since `my_class` is not
|
|
an associated class of `less_than_comparable<my_class>`. Thus only use this technique
|
|
if all else fails.
|
|
|
|
[endsect]
|
|
|
|
[section:portability 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 utility.utilities.operators.arithmetic.ex_oprs.operators1 `operators<>`]
|
|
and [link utility.utilities.operators.arithmetic.ex_oprs.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]
|
|
|
|
[endsect]
|
|
|
|
[section:arithmetic 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.
|
|
|
|
[section:smpl_oprs 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 utility.utilities.operators.usage.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]]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.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]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.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]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.addable1]`addable<T>`
|
|
|
|
`addable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator+(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp += t1`.
|
|
|
|
Return convertible to `T`. See the [link utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.subtractable1]`subtractable<T>`
|
|
|
|
`subtractable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator-(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp -= t1`.
|
|
|
|
Return convertible to `T`. See the [link utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.subtractable2_left]`subtractable2_left<T,U>`
|
|
]
|
|
|
|
[
|
|
`T operator-(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(u); temp -= t`.
|
|
|
|
Return convertible to `T`.
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.multipliable1]`multipliable<T>`
|
|
|
|
`multipliable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator*(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp *= t1`.
|
|
|
|
Return convertible to `T`. See the [link utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.dividable1]`dividable<T>`
|
|
|
|
`dividable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator/(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp /= t1`.
|
|
|
|
Return convertible to `T`. See the [link utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.dividable2_left]`dividable2_left<T,U>`
|
|
]
|
|
|
|
[
|
|
`T operator/(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(u); temp /= t`.
|
|
|
|
Return convertible to `T`.
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.modable1]`modable<T>`
|
|
|
|
`modable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator%(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp %= t1`.
|
|
|
|
Return convertible to `T`. See the [link utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.modable2_left]`modable2_left<T,U>`
|
|
]
|
|
|
|
[
|
|
`T operator%(const U&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(u); temp %= t`.
|
|
|
|
Return convertible to `T`.
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.orable1]`orable<T>`
|
|
|
|
`orable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator|(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp |= t1`.
|
|
|
|
Return convertible to `T`. See the [link utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.andable1]`andable<T>`
|
|
|
|
`andable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator&(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp &= t1`.
|
|
|
|
Return convertible to `T`. See the [link utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.xorable1]`xorable<T>`
|
|
|
|
`xorable1<T>`
|
|
]
|
|
|
|
[
|
|
`T operator^(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); temp ^= t1`.
|
|
|
|
Return convertible to `T`. See the [link utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.incrementable]`incrementable<T>`
|
|
]
|
|
|
|
[
|
|
`T operator++(T&, int)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); ++t`
|
|
|
|
Return convertible to `T`.
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.decrementable]`decrementable<T>`
|
|
]
|
|
|
|
[
|
|
`T operator--(T&, int)`
|
|
]
|
|
|
|
[
|
|
`T temp(t); --t;`
|
|
|
|
Return convertible to `T`.
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.symmetry Symmetry Note].
|
|
]
|
|
|
|
[No]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.equivalent1]`equivalent<T>`
|
|
|
|
__equivalent1__`<T>`
|
|
]
|
|
|
|
[
|
|
`bool operator==(const T&, const T&)`
|
|
]
|
|
|
|
[
|
|
`t < t1`.
|
|
|
|
Return convertible to `bool`. See the [link utility.utilities.operators.arithmetic.smpl_oprs.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]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.equivalent2]`equivalent<T, U>`
|
|
|
|
__equivalent2__`<T, U>`
|
|
]
|
|
|
|
[
|
|
`bool operator==(const T&, const U&)`
|
|
]
|
|
|
|
[
|
|
`t < u`. `t > u`.
|
|
|
|
Returns convertible to `bool`. See the [link utility.utilities.operators.arithmetic.smpl_oprs.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]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.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]
|
|
]
|
|
]
|
|
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.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]
|
|
]
|
|
]
|
|
]
|
|
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.ordering]
|
|
['Ordering Note]: The [link utility.utilities.operators.arithmetic.smpl_oprs.less_than_comparable1 `less_than_comparable<T>`] and
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.partially_ordered1 `partially_ordered<T>`] templates provide the same set
|
|
of operations. However, the workings of [link utility.utilities.operators.arithmetic.smpl_oprs.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 utility.utilities.operators.arithmetic.smpl_oprs.partially_ordered1 `partially_ordered<T>`] should be
|
|
used. The [link utility.utilities.operators.arithmetic.smpl_oprs.partially_ordered1 `partially_ordered<T>`] template can
|
|
be used for a totally-ordered type, but it is not as efficient as
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.less_than_comparable1 `less_than_comparable<T>`]. This
|
|
rule also applies for [link utility.utilities.operators.arithmetic.smpl_oprs.less_than_comparable2 `less_than_comparable<T, U>`] and
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.partially_ordered2 `partially_ordered<T,U>`] with respect to the ordering
|
|
of all `T` and `U` values, and for both versions of
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.equivalent1 `equivalent<>`]. The solution for
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.equivalent1 `equivalent<>`] is to write a custom
|
|
`operator==` for the target class.
|
|
|
|
[#utility.utilities.operators.arithmetic.smpl_oprs.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:
|
|
|
|
[:['C++11 [sect]3.7.3/3 \[basic.stc.auto\]: Automatic storage duration:] If a variable with automatic storage
|
|
duration 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/move may be eliminated as specified in 12.8.]
|
|
|
|
The reference to [sect]12.8 is important for us:
|
|
|
|
[:['C++11 [sect]12.8/31 \[class.copy\]: Copying and moving class objects:] When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class
|
|
object, even if the copy/move constructor and/or destructor for the object have side effects. ([hellip]) This elision of copy/move
|
|
operations, called ['copy elision], is permitted in the following circumstances (which may be combined to
|
|
eliminate multiple copies):
|
|
|
|
[mdash] in a `return` statement in a function with a class return type, when the expression is the name of a
|
|
non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-
|
|
unqualified type as the function return type, the copy/move operation can be omitted by constructing
|
|
the automatic object directly into the function's return value
|
|
|
|
([hellip])]
|
|
|
|
This optimization is known as the named return value optimization ([@https://en.cppreference.com/w/cpp/language/copy_elision#Non-mandatory_elision_of_copy.2Fmove_.28since_C.2B.2B11.29_operations 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 (C++11 [sect]12.2/2 \[class.temporary\])
|
|
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.
|
|
|
|
[endsect]
|
|
|
|
[section:grpd_oprs 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 utility.utilities.operators.arithmetic.grpd_oprs.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 utility.utilities.operators.usage.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]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.totally_ordered1] `totally_ordered<T>`
|
|
|
|
__totally_ordered1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.less_than_comparable1 `less_than_comparable<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.equality_comparable1 `equality_comparable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.totally_ordered2]`totally_ordered<T,U>`
|
|
|
|
__totally_ordered2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.less_than_comparable2 `less_than_comparable<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.equality_comparable2 `equality_comparable<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.additive1]`additive<T>`
|
|
|
|
__additive1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.addable1 `addable<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.subtractable1 `subtractable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.additive2]`additive<T, U>`
|
|
|
|
__additive2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.addable2 `addable<T, U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.subtractable2 `subtractable<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.multiplicative1] `multiplicative<T>`
|
|
|
|
__multiplicative1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.multipliable1 `multipliable<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.dividable1 `dividable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.multiplicative2]`multiplicative<T,U>`
|
|
|
|
__multiplicative2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.multipliable2 `multipliable<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.dividable2 `dividable<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.integer_multiplicative1] `integer_multiplicative<T>`
|
|
|
|
__integer_multiplicative1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.multiplicative1 `multiplicative<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.modable1 `modable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.integer_multiplicative2] `integer_multiplicative<T,U>`
|
|
|
|
__integer_multiplicative2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.multiplicative2 `multiplicative<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.modable2 `modable<T, U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.arithmetic1]`arithmetic<T>`
|
|
|
|
__arithmetic1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.additive1 `additive<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.multiplicative1 `multiplicative<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.arithmetic2]`arithmetic<T, U>`
|
|
|
|
__arithmetic2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.additive2 `additive<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.multiplicative2 `multiplicative<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.integer_arithmetic1] `integer_arithmetic<T>`
|
|
|
|
__integer_arithmetic1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.additive1 `additive<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.integer_multiplicative1 `integer_multiplicative<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.integer_arithmetic2]`integer_arithmetic<T, U>`
|
|
|
|
__integer_arithmetic2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.additive2 `additive<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.integer_multiplicative2 `integer_multiplicative<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.bitwise1]`bitwise<T>`
|
|
|
|
__bitwise1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.xorable1 `xorable<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.andable1 `andable<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.orable1 `orable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.bitwise2]`bitwise<T, U>`
|
|
|
|
__bitwise2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.xorable2 `xorable<T, U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.andable2 `andable<T, U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.orable2 `orable<T, U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.unit_steppable] `unit_steppable<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.incrementable `incrementable<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.decrementable `decrementable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.shiftable1]`shiftable<T>`
|
|
|
|
__shiftable1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.left_shiftable1 `left_shiftable<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.right_shiftable1 `right_shiftable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.shiftable2]`shiftable<T, U>`
|
|
|
|
__shiftable2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.left_shiftable2 `left_shiftable<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.right_shiftable2 `right_shiftable<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.ring_operators1] `ring_operators<T>`
|
|
|
|
__ring_operators1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.additive1 `additive<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.multipliable1 `multipliable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.ring_operators2]`ring_operators<T,U>`
|
|
|
|
__ring_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.additive2 `additive<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.subtractable2_left `subtractable2_left<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.multipliable2 `multipliable<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.ordered_ring_operators1] `ordered_ring_operators<T>`
|
|
|
|
__ordered_ring_operators1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.ring_operators1 `ring_operators<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.totally_ordered1 `totally_ordered<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.ordered_ring_operators2] `ordered_ring_operators<T,U>`
|
|
|
|
__ordered_ring_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.ring_operators2 `ring_operators<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.totally_ordered2 `totally_ordered<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.field_operators1]`field_operators<T>`
|
|
|
|
__field_operators1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.ring_operators1 `ring_operators<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.dividable1 `dividable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.field_operators2]`field_operators<T,U>`
|
|
|
|
__field_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.ring_operators2 `ring_operators<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.dividable2 `dividable<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.dividable2_left `dividable2_left<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.ordered_field_operators1]`ordered_field_operators<T>`
|
|
|
|
__ordered_field_operators1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.field_operators1 `field_operators<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.totally_ordered1 `totally_ordered<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.ordered_field_operators2]`ordered_field_operators<T,U>`
|
|
|
|
__ordered_field_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.field_operators2 `field_operators<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.totally_ordered2 `totally_ordered<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.euclidean_ring_operators1]`euclidean_ring_operators<T>`
|
|
|
|
__euclidean_ring_operators1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.ring_operators1 `ring_operators<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.dividable1 `dividable<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.modable1 `modable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.euclidean_ring_operators2] `euclidean_ring_operators<T,U>`
|
|
|
|
__euclidean_ring_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.ring_operators2 `ring_operators<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.dividable2 `dividable<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.dividable2_left `dividable2_left<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.modable2 `modable<T, U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.modable2_left `modable2_left<T,U>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.ordered_euclidean_ring_operators1] `ordered_euclidean_ring_operators<T>`
|
|
|
|
__ordered_euclidean_ring_operators1__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.euclidean_ring_operators1 `euclidean_ring_operators<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.totally_ordered1 `totally_ordered<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.ordered_euclidean_ring_operators2]`ordered_euclidean_ring_operators<T,U>`
|
|
|
|
__ordered_euclidean_ring_operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.euclidean_ring_operators2 `euclidean_ring_operators<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.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.
|
|
|
|
[endsect]
|
|
|
|
[section:ex_oprs Example Templates]
|
|
|
|
The arithmetic operator class templates [link utility.utilities.operators.arithmetic.ex_oprs.operators1 `operators<>`] and
|
|
[link utility.utilities.operators.arithmetic.ex_oprs.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 utility.utilities.operators.usage.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]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.ex_oprs.operators1]__operators__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.totally_ordered1 `totally_ordered<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.integer_arithmetic1 `integer_arithmetic<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.bitwise1 `bitwise<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.unit_steppable `unit_steppable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.arithmetic.ex_oprs.operators2]__operators__`<T, U>`
|
|
|
|
__operators2__`<T, U>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.totally_ordered2 `totally_ordered<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.integer_arithmetic2 `integer_arithmetic<T,U>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.bitwise2 `bitwise<T, U>`]
|
|
]
|
|
]
|
|
]
|
|
|
|
[#utility.utilities.operators.arithmetic.grpd_oprs.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]
|
|
|
|
[endsect]
|
|
|
|
[section:deref Dereference Operators and Iterator Helpers]
|
|
|
|
The [link utility.utilities.operators.deref.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 utility.utilities.operators.deref.dereference dereference operators] were motivated by
|
|
the [link utility.utilities.operators.deref.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.
|
|
|
|
[section:dereference Dereference Operators]
|
|
|
|
All the dereference operator templates in this table accept an
|
|
optional template parameter (not shown) to be used for
|
|
[link utility.utilities.operators.usage.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]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.dereference.dereferenceable]__dereferenceable__`<T,P>`
|
|
]
|
|
[
|
|
`P operator->() const`
|
|
]
|
|
[
|
|
`*i`. Address of the returned value convertible to `P`.
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.dereference.indexable]__indexable__`<T, D, R>`
|
|
]
|
|
[
|
|
`R operator[](D n) const`
|
|
]
|
|
[
|
|
`*(i + n)`. Return of type `R`.
|
|
]
|
|
]
|
|
]
|
|
|
|
[endsect]
|
|
|
|
[section:grpd_iter_oprs 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 utility.utilities.operators.usage.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]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.grpd_iter_oprs.input_iteratable]__input_iteratable__`<T, P>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.equality_comparable1 `equality_comparable<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.incrementable `incrementable<T>`]
|
|
|
|
[link utility.utilities.operators.deref.dereference.dereferenceable `dereferenceable<T,P>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.grpd_iter_oprs.output_iteratable]__output_iteratable__`<T>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.incrementable `incrementable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.grpd_iter_oprs.forward_iteratable]__forward_iteratable__`<T, P>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.deref.grpd_iter_oprs.input_iteratable `input_iteratable<T,P>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.grpd_iter_oprs.bidirectional_iteratable] __bidirectional_iteratable__`<T,P>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.deref.grpd_iter_oprs.forward_iteratable `forward_iteratable<T, P>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.smpl_oprs.decrementable `decrementable<T>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.grpd_iter_oprs.random_access_iteratable] __random_access_iteratable__`<T, P, D, R>`
|
|
]
|
|
[
|
|
[link utility.utilities.operators.deref.grpd_iter_oprs.bidirectional_iteratable `bidirectional_iteratable<T, P>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.totally_ordered1 `totally_ordered<T>`]
|
|
|
|
[link utility.utilities.operators.arithmetic.grpd_oprs.additive2 `additive<T, D>`]
|
|
|
|
[link utility.utilities.operators.deref.dereference.indexable `indexable<T, D, R>`]
|
|
]
|
|
]
|
|
]
|
|
|
|
[endsect]
|
|
|
|
[section:iterator Iterator Helpers]
|
|
|
|
There are also five iterator helper class templates, each
|
|
corresponding to a different iterator category. These classes cannot be
|
|
used for [link utility.utilities.operators.usage.chaining base class chaining]. The following
|
|
summaries show that these class templates supply both the iterator
|
|
operators from the [link utility.utilities.operators.deref.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]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.iterator.input_iterator_helper]__input_iterator_helper__`<T, V, D, P, R>`
|
|
]
|
|
[
|
|
Supports the operations and has the requirements of [link utility.utilities.operators.deref.grpd_iter_oprs.input_iteratable `input_iteratable<T, P>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.iterator.output_iterator_helper]__output_iterator_helper__`<T>`
|
|
]
|
|
[
|
|
Supports the operations and has the requirements of [link utility.utilities.operators.deref.grpd_iter_oprs.output_iteratable `output_iteratable<T>`]
|
|
|
|
See also \[[link note:1 1]\], \[[link note:2 2]\].
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.iterator.forward_iterator_helper] __forward_iterator_helper__`<T, V, D, P, R>`
|
|
]
|
|
[
|
|
Supports the operations and has the requirements of [link utility.utilities.operators.deref.grpd_iter_oprs.forward_iteratable `forward_iteratable<T, P>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.iterator.bidirectional_iterator_helper] __bidirectional_iterator_helper__`<T, V, D, P, R>`
|
|
]
|
|
[
|
|
Supports the operations and has the requirements of [link utility.utilities.operators.deref.grpd_iter_oprs.bidirectional_iteratable `bidirectional_iteratable<T, P>`]
|
|
]
|
|
]
|
|
[
|
|
[
|
|
[#utility.utilities.operators.deref.iterator.random_access_iterator_helper]__random_access_iterator_helper__`<T, V, D, P, R>`
|
|
]
|
|
[
|
|
Supports the operations and has the requirements of [link utility.utilities.operators.deref.grpd_iter_oprs.random_access_iteratable `random_access_iteratable<T, P, D, R>`]
|
|
|
|
To satisfy __RandomAccessIterator__, `x1 - x2` with return convertible to `D` is also required.
|
|
]
|
|
]
|
|
]
|
|
|
|
[#utility.utilities.operators.deref.iterator.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` (C++11 [sect]24.4.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 (C++11 [sect]24.5.2 \[insert.iterators\]) and stream iterators (C++11 [sect]24.6 \[stream.iterators\]) 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:/libs/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.
|
|
|
|
[endsect]
|
|
|
|
[section:i_demo 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]
|
|
|
|
[endsect]
|
|
|
|
[section:old_lib_note Note for Users of Older Versions]
|
|
|
|
The [link utility.utilities.operators.usage.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 utility.utilities.operators.usage.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 utility.utilities.operators.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 [ndash] the language rules
|
|
allow the compiler to apply the [@https://en.cppreference.com/w/cpp/language/ebo 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 [sect]10 \[class.derived\] paragraph 8 of the C++11 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[hellip]". 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]
|
|
|
|
[section:contributors Acknowledgments]
|
|
|
|
* [@http://www.boost.org/people/dave_abrahams.htm Dave Abrahams]:
|
|
Started the library and contributed the arithmetic operators in
|
|
[@../../../../boost/operators.hpp `boost/operators.hpp`].
|
|
|
|
* [@http://www.boost.org/people/jeremy_siek.htm Jeremy Siek]:
|
|
Contributed the [link utility.utilities.operators.deref dereference operators and iterator
|
|
helpers] in [@../../../../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 utility.utilities.operators.usage.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]
|