8#ifndef STLAB_ENUM_OPS_HPP
9#define STLAB_ENUM_OPS_HPP
151namespace implementation {
163 has_enabled_bitmask_t<T>::value || has_deprecated_bitmask_t<T>::value;
171template <
class,
bool>
172struct safe_underlying_type;
175struct safe_underlying_type<T, true> {
176 using type = std::underlying_type_t<T>;
180struct safe_underlying_type<T, false> {
185using safe_underlying_type_t =
typename safe_underlying_type<T, std::is_enum<T>::value>::type;
187template <
class U,
class T>
188using is_convertible_to_underlying =
189 std::is_convertible<U, stlab::implementation::safe_underlying_type_t<T>>;
203 implementation::has_deprecated_bitmask_t<T>::value;
208 implementation::has_deprecated_arithmetic_t<T>::value;
211template <
class U,
class T>
227constexpr auto operator&(T lhs, T rhs) -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T> {
228 using underlying = std::underlying_type_t<T>;
230 return static_cast<T
>(
static_cast<underlying
>(lhs) &
static_cast<underlying
>(rhs));
235constexpr auto operator~(T a) -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T> {
236 using underlying = std::underlying_type_t<T>;
238 return static_cast<T
>(~static_cast<underlying>(a));
243constexpr auto operator|(T lhs, T rhs) -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T> {
244 using underlying = std::underlying_type_t<T>;
246 return static_cast<T
>(
static_cast<underlying
>(lhs) |
static_cast<underlying
>(rhs));
251constexpr auto operator^(T lhs, T rhs) -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T> {
252 using underlying = std::underlying_type_t<T>;
254 return static_cast<T
>(
static_cast<underlying
>(lhs) ^
static_cast<underlying
>(rhs));
260 -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T> {
261 using underlying = std::make_unsigned_t<std::underlying_type_t<T>>;
263 return static_cast<T
>(
static_cast<underlying
>(lhs) <<
static_cast<underlying
>(rhs));
269 -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T> {
270 using underlying = std::make_unsigned_t<std::underlying_type_t<T>>;
272 return static_cast<T
>(
static_cast<underlying
>(lhs) >>
static_cast<underlying
>(rhs));
277constexpr auto operator^=(T& lhs, T rhs) -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T&> {
278 return lhs = lhs ^ rhs;
283constexpr auto operator&=(T& lhs, T rhs) -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T&> {
284 return lhs = lhs & rhs;
289constexpr auto operator|=(T& lhs, T rhs) -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T&> {
290 return lhs = lhs | rhs;
296 -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T&> {
297 return lhs = lhs << rhs;
303 -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T&> {
304 return lhs = lhs >> rhs;
307template <
class T,
class U>
312 assert(rhs == 0 || rhs == 1);
313 using underlying = std::underlying_type_t<T>;
315 return static_cast<T
>(
static_cast<underlying
>(lhs) -
static_cast<underlying
>(rhs));
322 -> std::enable_if_t<stlab::has_enabled_bitmask<T>, T> {
326template <
class T,
class U>
331 assert(rhs == 0 || rhs == 1);
332 using underlying = std::underlying_type_t<T>;
334 return static_cast<T
>(
static_cast<underlying
>(lhs) +
static_cast<underlying
>(rhs));
337template <
class U,
class T>
342 assert(lhs == 0 || lhs == 1);
343 using underlying = std::underlying_type_t<T>;
345 return static_cast<T
>(
static_cast<underlying
>(lhs) +
static_cast<underlying
>(rhs));
357constexpr auto operator+(T a) -> std::enable_if_t<stlab::has_enabled_arithmetic<T>, T> {
358 using underlying = std::underlying_type_t<T>;
360 return static_cast<T
>(+
static_cast<underlying
>(a));
365constexpr auto operator+(T lhs, T rhs) -> std::enable_if_t<stlab::has_enabled_arithmetic<T>, T> {
366 using underlying = std::underlying_type_t<T>;
368 return static_cast<T
>(
static_cast<underlying
>(lhs) +
static_cast<underlying
>(rhs));
373constexpr auto operator-(T lhs, T rhs) -> std::enable_if_t<stlab::has_enabled_arithmetic<T>, T> {
374 using underlying = std::underlying_type_t<T>;
376 return static_cast<T
>(
static_cast<underlying
>(lhs) -
static_cast<underlying
>(rhs));
379template <
class T,
class U>
383 using underlying = std::underlying_type_t<T>;
385 return static_cast<T
>(
static_cast<underlying
>(lhs) * rhs);
388template <
class U,
class T>
392 using underlying = std::underlying_type_t<T>;
394 return static_cast<T
>(lhs *
static_cast<underlying
>(rhs));
397template <
class T,
class U>
401 using underlying = std::underlying_type_t<T>;
403 return static_cast<T
>(
static_cast<underlying
>(lhs) / rhs);
406template <
class T,
class U>
410 using underlying = std::underlying_type_t<T>;
412 return static_cast<T
>(
static_cast<underlying
>(lhs) % rhs);
417constexpr auto operator+=(T& lhs, T rhs) -> std::enable_if_t<stlab::has_enabled_arithmetic<T>, T&> {
418 return lhs = lhs + rhs;
423constexpr auto operator-=(T& lhs, T rhs) -> std::enable_if_t<stlab::has_enabled_arithmetic<T>, T&> {
424 return lhs = lhs - rhs;
427template <
class T,
class U>
431 return lhs = lhs * rhs;
434template <
class T,
class U>
438 return lhs = lhs / rhs;
441template <
class T,
class U>
445 return lhs = lhs % rhs;
450constexpr auto operator++(T& lhs) -> std::enable_if_t<stlab::has_enabled_arithmetic<T>, T&> {
451 return lhs +=
static_cast<T
>(1);
456constexpr auto operator++(T& lhs,
int) -> std::enable_if_t<stlab::has_enabled_arithmetic<T>, T> {
458 lhs +=
static_cast<T
>(1);
464constexpr auto operator--(T& lhs) -> std::enable_if_t<stlab::has_enabled_arithmetic<T>, T&> {
465 return lhs -=
static_cast<T
>(1);
470constexpr auto operator--(T& lhs,
int) -> std::enable_if_t<stlab::has_enabled_arithmetic<T>, T> {
472 lhs -=
static_cast<T
>(1);
488 using underlying = std::underlying_type_t<T>;
490 return static_cast<T
>(-
static_cast<underlying
>(a));
519 return !(lhs == rhs);
528 return !(lhs == rhs);
535 return !
static_cast<bool>(lhs);
constexpr auto operator/(T lhs, U rhs) -> std::enable_if_t< stlab::has_enabled_arithmetic< T > &&stlab::is_compatible_scalar< U, T >, T >
Division by a scalar value.
Definition enum_ops.hpp:399
constexpr auto operator++(T &lhs) -> std::enable_if_t< stlab::has_enabled_arithmetic< T >, T & >
Prefix increment for arithmetic-enabled enums.
Definition enum_ops.hpp:450
constexpr auto operator-=(T &lhs, T rhs) -> std::enable_if_t< stlab::has_enabled_arithmetic< T >, T & >
Subtraction assignment for arithmetic-enabled enums.
Definition enum_ops.hpp:423
constexpr auto operator/=(T &lhs, U rhs) -> std::enable_if_t< stlab::has_enabled_arithmetic< T > &&stlab::is_compatible_scalar< U, T >, T & >
Division assignment by a scalar value.
Definition enum_ops.hpp:436
constexpr auto operator*(T lhs, U rhs) -> std::enable_if_t< stlab::has_enabled_arithmetic< T > &&stlab::is_compatible_scalar< U, T >, T >
Multiplication by a scalar value.
Definition enum_ops.hpp:381
constexpr auto operator*=(T &lhs, U rhs) -> std::enable_if_t< stlab::has_enabled_arithmetic< T > &&stlab::is_compatible_scalar< U, T >, T & >
Multiplication assignment by a scalar value.
Definition enum_ops.hpp:429
constexpr auto operator%(T lhs, U rhs) -> std::enable_if_t< stlab::has_enabled_arithmetic< T > &&stlab::is_compatible_scalar< U, T >, T >
Modulo by a scalar value.
Definition enum_ops.hpp:408
constexpr auto operator+=(T &lhs, T rhs) -> std::enable_if_t< stlab::has_enabled_arithmetic< T >, T & >
Addition assignment for arithmetic-enabled enums.
Definition enum_ops.hpp:417
constexpr auto operator%=(T &lhs, U rhs) -> std::enable_if_t< stlab::has_enabled_arithmetic< T > &&stlab::is_compatible_scalar< U, T >, T & >
Modulo assignment by a scalar value.
Definition enum_ops.hpp:443
constexpr auto operator--(T &lhs) -> std::enable_if_t< stlab::has_enabled_arithmetic< T >, T & >
Prefix decrement for arithmetic-enabled enums.
Definition enum_ops.hpp:464
constexpr auto operator|=(T &lhs, T rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T & >
OR-assign for bitmask-enabled enums.
Definition enum_ops.hpp:289
constexpr auto operator&(T lhs, T rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T >
Bitwise AND for bitmask-enabled enums; returns the same enum type.
Definition enum_ops.hpp:227
constexpr auto operator~(T a) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T >
Bitwise NOT for bitmask-enabled enums; returns the same enum type.
Definition enum_ops.hpp:235
constexpr auto operator>>=(T &lhs, std::size_t rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T & >
Right shift-assign for bitmask-enabled enums.
Definition enum_ops.hpp:302
constexpr auto operator^=(T &lhs, T rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T & >
XOR-assign for bitmask-enabled enums.
Definition enum_ops.hpp:277
constexpr auto operator|(T lhs, T rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T >
Bitwise OR for bitmask-enabled enums.
Definition enum_ops.hpp:243
constexpr auto operator<<(T lhs, std::size_t rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T >
Left shift for bitmask-enabled enums.
Definition enum_ops.hpp:259
constexpr auto operator+(T lhs, U rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T > &&stlab::is_compatible_scalar< U, T >, T >
Adds a 0 or 1 scalar value to a bitmask-enabled enum. Allows expressions like e & (e + 1) to clear tr...
Definition enum_ops.hpp:329
constexpr auto operator-(T lhs, U rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T > &&stlab::is_compatible_scalar< U, T >, T >
Subtracts a 0 or 1 scalar value from a bitmask-enabled enum. Allows expressions like e & (e - 1) to c...
Definition enum_ops.hpp:310
constexpr auto operator>>(T lhs, std::size_t rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T >
Right shift for bitmask-enabled enums.
Definition enum_ops.hpp:268
constexpr auto operator&=(T &lhs, T rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T & >
AND-assign for bitmask-enabled enums.
Definition enum_ops.hpp:283
constexpr auto operator^(T lhs, T rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T >
Bitwise XOR for bitmask-enabled enums.
Definition enum_ops.hpp:251
constexpr auto operator<<=(T &lhs, std::size_t rhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >, T & >
Left shift-assign for bitmask-enabled enums.
Definition enum_ops.hpp:295
constexpr auto operator!(T lhs) -> std::enable_if_t< stlab::has_enabled_bitmask< T >||stlab::has_enabled_arithmetic< T >, bool >
Logical NOT for bitmask or arithmetic enums; true when the value converts to false.
Definition enum_ops.hpp:533
constexpr auto operator==(T lhs, std::nullptr_t) -> std::enable_if_t<(stlab::has_enabled_bitmask< T >||stlab::has_enabled_arithmetic< T >) &&!stlab::is_compatible_scalar< T, T >, bool >
Equality with nullptr for bitmask or arithmetic scoped enums; true when the value is zero.
Definition enum_ops.hpp:496
constexpr auto operator!=(T lhs, std::nullptr_t rhs) -> std::enable_if_t<(stlab::has_enabled_bitmask< T >||stlab::has_enabled_arithmetic< T >) &&!stlab::is_compatible_scalar< T, T >, bool >
Inequality with nullptr for bitmask or arithmetic scoped enums.
Definition enum_ops.hpp:515
auto adobe_enable_bitmask_enum(...) -> std::false_type
auto stlab_enable_arithmetic_enum(...) -> std::false_type
Overload this for your enum in the enum namespace to return std::true_type and enable arithmetic oper...
auto adobe_enable_arithmetic_enum(...) -> std::false_type
auto stlab_enable_bitmask_enum(...) -> std::false_type
Overload this for your enum in the enum namespace to return std::true_type and enable bitwise operato...
constexpr bool is_compatible_scalar
Whether the scalar type U is compatible with the enum type T.
Definition enum_ops.hpp:212
constexpr bool has_enabled_arithmetic
Whether the enum type has enabled arithmetic operations.
Definition enum_ops.hpp:207
constexpr bool has_enabled_bitmask
Whether the enum type has enabled bitmask operations.
Definition enum_ops.hpp:202
The stlab namespace.
Definition enum_ops.hpp:122