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 # pragma nv_diagnostic push
109 # pragma nv_diag_suppress 174
112 constexpr
bool is_bitmask_v<
E, std::enable_if_t<(E::IS_ATH_BITMASK,1)>> =
true;
114 # pragma nv_diagnostic pop
131 std::enable_if_t<is_bitmask_v<E>,
E>
134 typedef std::underlying_type_t<E> underlying;
135 return static_cast<E> (~static_cast<underlying>(lhs));
144 template <
class E,
class F,
145 typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) &&
146 has_same_underlying_v<E,F>>>
147 constexpr
auto operator& (
E lhs,
F rhs)
149 typedef relaxed_underlying_type_t<E> underlying;
150 return static_cast<enum_or_underlying_t<E,F>
>(
static_cast<underlying
>(lhs) &
151 static_cast<underlying
>(rhs));
157 template <
class E,
class F,
158 typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) &&
159 has_same_underlying_v<E,F>>>
160 constexpr
auto operator| (
E lhs,
F rhs)
162 typedef relaxed_underlying_type_t<E> underlying;
163 return static_cast<enum_or_underlying_t<E,F>
>(
static_cast<underlying
>(lhs) |
164 static_cast<underlying
>(rhs));
170 template <
class E,
class F,
171 typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) &&
172 has_same_underlying_v<E,F>>>
173 constexpr
auto operator^ (
E lhs,
F rhs)
175 typedef relaxed_underlying_type_t<E> underlying;
176 return static_cast<enum_or_underlying_t<E,F>
>(
static_cast<underlying
>(lhs) ^
177 static_cast<underlying
>(rhs));
184 std::enable_if_t<is_bitmask_v<E>,
E&>
187 typedef std::underlying_type_t<E> underlying;
188 lhs =
static_cast<E> (
static_cast<underlying
>(lhs) &
static_cast<underlying
>(rhs));
196 std::enable_if_t<is_bitmask_v<E>,
E&>
199 typedef std::underlying_type_t<E> underlying;
200 lhs =
static_cast<E> (
static_cast<underlying
>(lhs) |
static_cast<underlying
>(rhs));
208 std::enable_if_t<is_bitmask_v<E>,
E&>
211 typedef std::underlying_type_t<E> underlying;
212 lhs =
static_cast<E> (
static_cast<underlying
>(lhs) ^
static_cast<underlying
>(rhs));
231 std::enable_if_t<is_bitmask_v<E>,
E&>
250 std::enable_if_t<is_bitmask_v<E>,
E&>
269 std::enable_if_t<is_bitmask_v<E>,
bool>
272 typedef std::underlying_type_t<E>underlying;
273 return static_cast<underlying
> (lhs & rhs) != 0;
280 #endif // not CXXUTILS_BITMASK_H