8#ifndef STLAB_ENUM_OPS_HPP
9#define STLAB_ENUM_OPS_HPP
80namespace implementation {
88constexpr bool has_enabled_bitmask = has_enabled_bitmask_t<T>::value;
94constexpr bool has_enabled_arithmetic = has_enabled_arithmetic_t<T>::value;
96template <
class T,
class U>
97using enable_if_bitmask_or_arithmetic =
98 std::enable_if_t<std::disjunction_v<stlab::implementation::has_enabled_bitmask_t<T>,
99 stlab::implementation::has_enabled_arithmetic_t<T>>,
102template <
class,
bool>
103struct safe_underlying_type;
106struct safe_underlying_type<T, true> {
107 using type = std::underlying_type_t<T>;
111struct safe_underlying_type<T, false> {
116using safe_underlying_type_t =
typename safe_underlying_type<T, std::is_enum<T>::value>::type;
118template <
class U,
class T>
119using is_convertible_to_underlying =
120 std::is_convertible<U, stlab::implementation::safe_underlying_type_t<T>>;
135 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T> {
136 using underlying = std::underlying_type_t<T>;
138 return static_cast<T
>(
static_cast<underlying
>(lhs) &
static_cast<underlying
>(rhs));
144 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T> {
145 using underlying = std::underlying_type_t<T>;
147 return static_cast<T
>(~static_cast<underlying>(a));
153 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T> {
154 using underlying = std::underlying_type_t<T>;
156 return static_cast<T
>(
static_cast<underlying
>(lhs) |
static_cast<underlying
>(rhs));
162 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T> {
163 using underlying = std::underlying_type_t<T>;
165 return static_cast<T
>(
static_cast<underlying
>(lhs) ^
static_cast<underlying
>(rhs));
171 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T> {
172 using underlying = std::make_unsigned_t<std::underlying_type_t<T>>;
174 return static_cast<T
>(
static_cast<underlying
>(lhs) <<
static_cast<underlying
>(rhs));
180 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T> {
181 using underlying = std::make_unsigned_t<std::underlying_type_t<T>>;
183 return static_cast<T
>(
static_cast<underlying
>(lhs) >>
static_cast<underlying
>(rhs));
189 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T&> {
190 return lhs = lhs ^ rhs;
196 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T&> {
197 return lhs = lhs & rhs;
203 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T&> {
204 return lhs = lhs | rhs;
210 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T&> {
211 return lhs = lhs << rhs;
217 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T>, T&> {
218 return lhs = lhs >> rhs;
221template <
class T,
class U>
224 -> std::enable_if_t<stlab::implementation::has_enabled_bitmask<T> &&
225 stlab::implementation::is_convertible_to_underlying<U, T>::value,
227 using underlying = std::underlying_type_t<T>;
229 return static_cast<T
>(
static_cast<underlying
>(lhs) -
static_cast<underlying
>(rhs));
237 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T>, T> {
238 using underlying = std::underlying_type_t<T>;
240 return static_cast<T
>(+
static_cast<underlying
>(a));
246 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T>, T> {
247 using underlying = std::underlying_type_t<T>;
249 return static_cast<T
>(-
static_cast<underlying
>(a));
255 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T>, T> {
256 using underlying = std::underlying_type_t<T>;
258 return static_cast<T
>(
static_cast<underlying
>(lhs) +
static_cast<underlying
>(rhs));
264 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T>, T> {
265 using underlying = std::underlying_type_t<T>;
267 return static_cast<T
>(
static_cast<underlying
>(lhs) -
static_cast<underlying
>(rhs));
270template <
class T,
class U>
273 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T> &&
274 stlab::implementation::is_convertible_to_underlying<U, T>::value,
276 using underlying = std::underlying_type_t<T>;
278 return static_cast<T
>(
static_cast<underlying
>(lhs) * rhs);
281template <
class U,
class T>
284 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T> &&
285 stlab::implementation::is_convertible_to_underlying<U, T>::value,
287 using underlying = std::underlying_type_t<T>;
289 return static_cast<T
>(lhs *
static_cast<underlying
>(rhs));
292template <
class T,
class U>
295 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T> &&
296 stlab::implementation::is_convertible_to_underlying<U, T>::value,
298 using underlying = std::underlying_type_t<T>;
300 return static_cast<T
>(
static_cast<underlying
>(lhs) / rhs);
303template <
class T,
class U>
306 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T> &&
307 stlab::implementation::is_convertible_to_underlying<U, T>::value,
309 using underlying = std::underlying_type_t<T>;
311 return static_cast<T
>(
static_cast<underlying
>(lhs) % rhs);
317 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T>, T&> {
318 return lhs = lhs + rhs;
324 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T>, T&> {
325 return lhs = lhs - rhs;
328template <
class T,
class U>
331 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T> &&
332 stlab::implementation::is_convertible_to_underlying<U, T>::value,
334 return lhs = lhs * rhs;
337template <
class T,
class U>
340 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T> &&
341 stlab::implementation::is_convertible_to_underlying<U, T>::value,
343 return lhs = lhs / rhs;
346template <
class T,
class U>
349 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T> &&
350 stlab::implementation::is_convertible_to_underlying<U, T>::value,
352 return lhs = lhs % rhs;
358 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T>, T&> {
359 return lhs +=
static_cast<T
>(1);
365 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T>, T> {
367 lhs +=
static_cast<T
>(1);
374 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T>, T&> {
375 return lhs -=
static_cast<T
>(1);
381 -> std::enable_if_t<stlab::implementation::has_enabled_arithmetic<T>, T> {
383 lhs -=
static_cast<T
>(1);
392 -> std::enable_if_t<(stlab::implementation::has_enabled_bitmask<T> ||
393 stlab::implementation::has_enabled_arithmetic<T>) &&
394 !stlab::implementation::is_convertible_to_underlying<T, T>::value,
402 -> std::enable_if_t<(stlab::implementation::has_enabled_bitmask<T> ||
403 stlab::implementation::has_enabled_arithmetic<T>) &&
404 !stlab::implementation::is_convertible_to_underlying<T, T>::value,
412 -> std::enable_if_t<(stlab::implementation::has_enabled_bitmask<T> ||
413 stlab::implementation::has_enabled_arithmetic<T>) &&
414 !stlab::implementation::is_convertible_to_underlying<T, T>::value,
416 return !(lhs == rhs);
422 -> std::enable_if_t<(stlab::implementation::has_enabled_bitmask<T> ||
423 stlab::implementation::has_enabled_arithmetic<T>) &&
424 !stlab::implementation::is_convertible_to_underlying<T, T>::value,
426 return !(lhs == rhs);
431constexpr auto operator!(T lhs) -> stlab::implementation::enable_if_bitmask_or_arithmetic<T, bool> {
432 return !
static_cast<bool>(lhs);
constexpr auto operator/=(T &lhs, U rhs) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T > &&stlab::implementation::is_convertible_to_underlying< U, T >::value, T & >
Division assignment by a value convertible to the enum's underlying type.
Definition enum_ops.hpp:339
constexpr auto operator==(T lhs, std::nullptr_t) -> std::enable_if_t<(stlab::implementation::has_enabled_bitmask< T >||stlab::implementation::has_enabled_arithmetic< T >) &&!stlab::implementation::is_convertible_to_underlying< T, T >::value, bool >
Equality with nullptr for bitmask or arithmetic scoped enums; true when the value is zero.
Definition enum_ops.hpp:391
constexpr auto operator|=(T &lhs, T rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T & >
OR-assign for bitmask-enabled enums.
Definition enum_ops.hpp:202
constexpr auto operator/(T lhs, U rhs) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T > &&stlab::implementation::is_convertible_to_underlying< U, T >::value, T >
Division by a value convertible to the enum's underlying type.
Definition enum_ops.hpp:294
constexpr auto operator+(T a) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T >, T >
Unary plus for arithmetic-enabled enums.
Definition enum_ops.hpp:236
constexpr auto operator<<=(T &lhs, std::size_t rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T & >
Left shift-assign for bitmask-enabled enums.
Definition enum_ops.hpp:209
constexpr auto operator-=(T &lhs, T rhs) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T >, T & >
Subtraction assignment for arithmetic-enabled enums.
Definition enum_ops.hpp:323
constexpr auto operator^=(T &lhs, T rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T & >
XOR-assign for bitmask-enabled enums.
Definition enum_ops.hpp:188
constexpr auto operator>>=(T &lhs, std::size_t rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T & >
Right shift-assign for bitmask-enabled enums.
Definition enum_ops.hpp:216
constexpr auto operator>>(T lhs, std::size_t rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T >
Right shift for bitmask-enabled enums.
Definition enum_ops.hpp:179
constexpr auto operator!=(T lhs, std::nullptr_t rhs) -> std::enable_if_t<(stlab::implementation::has_enabled_bitmask< T >||stlab::implementation::has_enabled_arithmetic< T >) &&!stlab::implementation::is_convertible_to_underlying< T, T >::value, bool >
Inequality with nullptr for bitmask or arithmetic scoped enums.
Definition enum_ops.hpp:411
constexpr auto operator*(T lhs, U rhs) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T > &&stlab::implementation::is_convertible_to_underlying< U, T >::value, T >
Multiplication by a value convertible to the enum's underlying type.
Definition enum_ops.hpp:272
constexpr auto operator!(T lhs) -> stlab::implementation::enable_if_bitmask_or_arithmetic< T, bool >
Logical NOT for bitmask or arithmetic enums; true when the value converts to false.
Definition enum_ops.hpp:431
constexpr auto operator+=(T &lhs, T rhs) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T >, T & >
Addition assignment for arithmetic-enabled enums.
Definition enum_ops.hpp:316
constexpr auto operator<<(T lhs, std::size_t rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T >
Left shift for bitmask-enabled enums.
Definition enum_ops.hpp:170
constexpr auto operator++(T &lhs) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T >, T & >
Prefix increment for arithmetic-enabled enums.
Definition enum_ops.hpp:357
constexpr auto operator^(T lhs, T rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T >
Bitwise XOR for bitmask-enabled enums.
Definition enum_ops.hpp:161
constexpr auto operator%(T lhs, U rhs) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T > &&stlab::implementation::is_convertible_to_underlying< U, T >::value, T >
Modulo by a value convertible to the enum's underlying type.
Definition enum_ops.hpp:305
constexpr auto operator&=(T &lhs, T rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T & >
AND-assign for bitmask-enabled enums.
Definition enum_ops.hpp:195
constexpr auto operator*=(T &lhs, U rhs) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T > &&stlab::implementation::is_convertible_to_underlying< U, T >::value, T & >
Multiplication assignment by a value convertible to the enum's underlying type.
Definition enum_ops.hpp:330
constexpr auto operator-(T lhs, U rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T > &&stlab::implementation::is_convertible_to_underlying< U, T >::value, T >
Subtracts a value convertible to the underlying type from a bitmask-enabled enum.
Definition enum_ops.hpp:223
constexpr auto operator--(T &lhs) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T >, T & >
Prefix decrement for arithmetic-enabled enums.
Definition enum_ops.hpp:373
constexpr auto operator%=(T &lhs, U rhs) -> std::enable_if_t< stlab::implementation::has_enabled_arithmetic< T > &&stlab::implementation::is_convertible_to_underlying< U, T >::value, T & >
Modulo assignment by a value convertible to the enum's underlying type.
Definition enum_ops.hpp:348
constexpr auto operator&(T lhs, T rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T >
Bitwise AND for bitmask-enabled enums; returns the same enum type.
Definition enum_ops.hpp:134
constexpr auto operator|(T lhs, T rhs) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T >
Bitwise OR for bitmask-enabled enums.
Definition enum_ops.hpp:152
constexpr auto operator~(T a) -> std::enable_if_t< stlab::implementation::has_enabled_bitmask< T >, T >
Bitwise NOT for bitmask-enabled enums; returns the same enum type.
Definition enum_ops.hpp:143
The stlab namespace.
Definition enum_ops.hpp:66
auto stlab_enable_arithmetic_enum(...) -> std::false_type
auto stlab_enable_bitmask_enum(...) -> std::false_type