This is a library that implements much of the functionality discussed in P1046: Automatically Generate More Operators. The summary of what is enabled this library is:
- Generate
lhs += rhs
aslhs = std::move(lhs) + rhs
, but evaluatelhs
only once - Generate
lhs -= rhs
aslhs = std::move(lhs) - rhs
, but evaluatelhs
only once - Generate
lhs *= rhs
aslhs = std::move(lhs) * rhs
, but evaluatelhs
only once - Generate
lhs /= rhs
aslhs = std::move(lhs) / rhs
, but evaluatelhs
only once - Generate
lhs %= rhs
aslhs = std::move(lhs) % rhs
, but evaluatelhs
only once - Generate
lhs &= rhs
aslhs = std::move(lhs) & rhs
, but evaluatelhs
only once - Generate
lhs |= rhs
aslhs = std::move(lhs) | rhs
, but evaluatelhs
only once - Generate
lhs ^= rhs
aslhs = std::move(lhs) ^ rhs
, but evaluatelhs
only once - Generate
lhs <<= rhs
aslhs = std::move(lhs) << rhs
, but evaluatelhs
only once - Generate
lhs >>= rhs
aslhs = std::move(lhs) >> rhs
, but evaluatelhs
only once - Generate
++x
asx += 1
- Generate
--x
asx -= 1
- Generate
x++
as++x
but return a copy of the original value - Generate
x--
as--x
but return a copy of the original value - Generate
lhs->rhs
as(*lhs).rhs
- Generate
lhs->*rhs
as(*lhs).*rhs
There are also some extensions described at the end of this document that are not being proposed for standardization at this time.
There is a convenience header operators/operators.hpp
that includes all other headers.
The proposal currently suggests that the language provides all of these by default. However, another option is to standardize some subset of the following library features. A third option is something like auto & operator+=(T &, U const &) = default;
.
Defined in header operators/compound_assignment.hpp
.
To create a definition of lhs @= rhs
in terms of lhs = std::move(lhs) @ rhs
, there are several options:
- For all types in a namespace, use any of the following in your namespace:
using operators::operator+=;
using operators::operator-=;
using operators::operator*=;
using operators::operator/=;
using operators::operator%=;
using operators::operator<<=;
using operators::operator>>=;
using operators::operator&=;
using operators::operator|=;
using operators::operator^=;
- For all of the previous operators and all types in a namespace, type
OPERATORS_IMPORT_COMPOUND_ASSIGNMENT
in your namespace. - For a specific type, derive from any of the following under the desired access control:
operators::plus_equal
operators::minus_equal
operators::times_equal
operators::divides_equal
operators::modulo_equal
operators::left_shift_equal
operators::right_shift_equal
operators::and_equal
operators::or_equal
operators::xor_equal
- For all of the previous operators and for a specific type, derive from
operators::compound_assignment
under the desired access control.
Defined in header operators/increment_decrement.hpp
.
To create a definition of ++a
in terms of a += 1
, there are two options:
- For all types in a namespace, use
using operators::prefix::operator++;
in your namespace. - For a specific type, derive from
operators::prefix::operator++
under the desired access control.
To create a definition of a++
in terms of ++a
(but return a copy of the original value for copyable types and return void
for non-copyable types), there are two options:
- For all types in a namespace, use
using operators::postfix::operator++;
in your namespace. - For a specific type, derive from
operators::postfix::operator++
under the desired access control.
To combine the previous two and define ++a
and a++
, there are two options:
- For all types in a namespace, use
using operators::operator++;
in your namespace. - For a specific type, derive from
operators::operator++
under the desired access control.
To create a definition of --a
in terms of a -= 1
, there are two options:
- For all types in a namespace, use
using operators::prefix::operator--;
in your namespace. - For a specific type, derive from
operators::prefix::operator--
under the desired access control.
To create a definition of a--
in terms of --a
(but return a copy of the original value for copyable types and return void
for non-copyable types), there are two options:
- For all types in a namespace, use
using operators::postfix::operator--;
in your namespace. - For a specific type, derive from
operators::postfix::operator--
under the desired access control.
To combine the previous two and define --a
and a--
, there are two options:
- For all types in a namespace, use
using operators::operator--;
in your namespace. - For a specific type, derive from
operators::operator--
under the desired access control.
Defined in header operators/arrow.hpp
.
There are currently two forms of operator->
supported by the operators
library.
To create a definition of lhs->rhs
defined in terms of *(lhs).rhs
that does not work for operator*
that returns by value, there are two options:
- For a specific type, type the macro
OPERATORS_ARROW_DEFINITIONS
in your class body under the desired access control. - For a specific type, derive from
operators::arrow<your_type_name>
under the desired access control.
To create a definition of lhs->rhs
defined in terms of *(lhs).rhs
that does work for operator*
that returns by value, but risks creating a dangling reference with some common refactorings, and can cause a move construction to occur, there are two options:
- For a specific type, type the macro
OPERATORS_ARROW_PROXY_DEFINITIONS
in your class body under the desired access control. - For a specific type, derive from
operators::arrow_proxy<your_type_name>
under the desired access control.
Defined in header operators/arrow_star.hpp
.
To create a definition of lhs->*rhs
defined in terms of (*lhs).*rhs
, there are two options:
- For all types in a namespace, use
using operators::operator->*;
in your namespace. - For a specific type, derive from
operators::arrow_star
under the desired access control.
Defined in header operators/bracket.hpp
.
There are currently two forms of operator[]
supported by the operators
library.
To create a definition of lhs[rhs]
defined in terms of *(lhs + rhs)
(suitable for iterators), there are two options:
- For a specific type, type the macro
OPERATORS_BRACKET_ITERATOR_DEFINITIONS
in your class body under the desired access control. - For a specific type, derive from
operators::bracket::iterator<your_type_name>
under the desired access control.
To create a definition of lhs[rhs]
defined in terms of *(begin(lhs) + rhs)
(suitable for range-access sequence ranges), there are two options:
- For a specific type, type the macro
OPERATORS_BRACKET_SEQUENCE_RANGE_DEFINITIONS
in your class body under the desired access control. - For a specific type, derive from
operators::bracket::sequence_range<your_type_name>
under the desired access control.
Defined in header operators/binary_minus.hpp
.
To create a definition of lhs - rhs
in terms of lhs + -rhs
, there are two options:
- For all types in a namespace, use
using operators::binary::operator-;
in your namespace. - For a specific type, derive from
operators::binary::minus
under the desired access control.
Note: do not combine this with unary operator-
. This will create a (diagnosed at compile time) circular dependency.
Defined in header operators/unary_minus.hpp
.
To create a definition of -a
in terms of 0 - a
, there are two options:
- For all types in a namespace, use
using operators::unary::operator-;
in your namespace. - For a specific type, derive from
operators::unary::minus
under the desired access control.
Note: do not combine this with binary operator-
. This will create a (diagnosed at compile time) circular dependency.
Defined in header operators/unary_plus.hpp
.
To create a definition of +a
as returning a copy of a
, there are two options:
- For all types in a namespace, use
using operators::unary::operator+;
in your namespace. - For a specific type, derive from
operators::unary::plus
under the desired access control.