55 #include <type_traits>
58 #ifndef CXXUTILS_BITMASK_H
59 #define CXXUTILS_BITMASK_H
70 #define ATH_BITMASK IS_ATH_BITMASK=1
77 template <
typename T,
bool = std::is_enum_v<T>>
78 struct relaxed_underlying_type {
79 using type = std::underlying_type_t<T>;
82 struct relaxed_underlying_type<
T, false> {
86 using relaxed_underlying_type_t =
typename relaxed_underlying_type<T>::type;
89 template <
class E,
class F>
90 constexpr
bool has_same_underlying_v = std::is_same_v<relaxed_underlying_type_t<E>,
91 relaxed_underlying_type_t<F>>;
94 template <
class E,
class F>
95 struct enum_or_underlying {
96 using type = std::conditional_t<std::is_same_v<E,F> && has_same_underlying_v<E,F>,
97 E, relaxed_underlying_type_t<E>>;
99 template <
class E,
class F>
100 using enum_or_underlying_t =
typename enum_or_underlying<E,F>::type;
103 template <
class E,
typename Enable =
void>
104 constexpr
bool is_bitmask_v =
false;
107 constexpr
bool is_bitmask_v<
E, std::enable_if_t<(E::IS_ATH_BITMASK,1)>> =
true;
123 std::enable_if_t<is_bitmask_v<E>,
E>
126 typedef std::underlying_type_t<E> underlying;
127 return static_cast<E> (~static_cast<underlying>(lhs));
136 template <
class E,
class F,
137 typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) &&
138 has_same_underlying_v<E,F>>>
139 constexpr
auto operator& (
E lhs,
F rhs)
141 typedef relaxed_underlying_type_t<E> underlying;
142 return static_cast<enum_or_underlying_t<E,F>
>(
static_cast<underlying
>(lhs) &
143 static_cast<underlying
>(rhs));
149 template <
class E,
class F,
150 typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) &&
151 has_same_underlying_v<E,F>>>
152 constexpr
auto operator| (
E lhs,
F rhs)
154 typedef relaxed_underlying_type_t<E> underlying;
155 return static_cast<enum_or_underlying_t<E,F>
>(
static_cast<underlying
>(lhs) |
156 static_cast<underlying
>(rhs));
162 template <
class E,
class F,
163 typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) &&
164 has_same_underlying_v<E,F>>>
165 constexpr
auto operator^ (
E lhs,
F rhs)
167 typedef relaxed_underlying_type_t<E> underlying;
168 return static_cast<enum_or_underlying_t<E,F>
>(
static_cast<underlying
>(lhs) ^
169 static_cast<underlying
>(rhs));
176 std::enable_if_t<is_bitmask_v<E>,
E&>
179 typedef std::underlying_type_t<E> underlying;
180 lhs =
static_cast<E> (
static_cast<underlying
>(lhs) &
static_cast<underlying
>(rhs));
188 std::enable_if_t<is_bitmask_v<E>,
E&>
191 typedef std::underlying_type_t<E> underlying;
192 lhs =
static_cast<E> (
static_cast<underlying
>(lhs) |
static_cast<underlying
>(rhs));
200 std::enable_if_t<is_bitmask_v<E>,
E&>
203 typedef std::underlying_type_t<E> underlying;
204 lhs =
static_cast<E> (
static_cast<underlying
>(lhs) ^
static_cast<underlying
>(rhs));
223 std::enable_if_t<is_bitmask_v<E>,
E&>
242 std::enable_if_t<is_bitmask_v<E>,
E&>
261 std::enable_if_t<is_bitmask_v<E>,
bool>
264 typedef std::underlying_type_t<E>underlying;
265 return static_cast<underlying
> (lhs & rhs) != 0;
272 #endif // not CXXUTILS_BITMASK_H