ATLAS Offline Software
Loading...
Searching...
No Matches
bitmask.h
Go to the documentation of this file.
1// This file's extension implies that it's C, but it's really -*- C++ -*-.
2/*
3 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
4*/
5/*
6 */
53
54
55#include <type_traits>
56
57
58#ifndef CXXUTILS_BITMASK_H
59#define CXXUTILS_BITMASK_H
60
61
70#define ATH_BITMASK IS_ATH_BITMASK=1
71
72
74namespace {
75
77 template <typename T, bool = std::is_enum_v<T>>
78 struct relaxed_underlying_type {
79 using type = std::underlying_type_t<T>;
80 };
81 template <typename T>
82 struct relaxed_underlying_type<T, false> {
83 using type = T;
84 };
85 template <class T>
86 using relaxed_underlying_type_t = typename relaxed_underlying_type<T>::type;
87
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>>;
92
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>>;
98 };
99 template <class E, class F>
100 using enum_or_underlying_t = typename enum_or_underlying<E,F>::type;
101
103 template <class E, typename Enable = void>
104 constexpr bool is_bitmask_v = false;
105
106#ifdef __CUDACC__
107# pragma nv_diagnostic push
108// expression has no effect
109# pragma nv_diag_suppress 174
110#endif
111 template <class E>
112 constexpr bool is_bitmask_v<E, std::enable_if_t<(E::IS_ATH_BITMASK,1)>> = true;
113#ifdef __CUDACC__
114# pragma nv_diagnostic pop
115#endif
116}
117
118
119/*
120 * Define bitwise operators for class enums.
121 * These all cast the operands to the underlying type, and then cast
122 * the result back again to the enumeration.
123 *
124 * These functions are enabled only for enumerators that have used the
125 * @c ATH_BITMASK macro.
126 */
127
129template <class E>
130constexpr
131std::enable_if_t<is_bitmask_v<E>, E>
133{
134 typedef std::underlying_type_t<E> underlying;
135 return static_cast<E> (~static_cast<underlying>(lhs));
136}
137
138
144template <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>>>
147constexpr auto operator& (E lhs, F rhs)
148{
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));
152}
153
154
157template <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>>>
160constexpr auto operator| (E lhs, F rhs)
161{
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));
165}
166
167
170template <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>>>
173constexpr auto operator^ (E lhs, F rhs)
174{
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));
178}
179
180
182template <class E>
183constexpr
184std::enable_if_t<is_bitmask_v<E>, E&>
185operator&= (E& lhs, E rhs)
186{
187 typedef std::underlying_type_t<E> underlying;
188 lhs = static_cast<E> (static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
189 return lhs;
190}
191
192
194template <class E>
195constexpr
196std::enable_if_t<is_bitmask_v<E>, E&>
197operator|= (E& lhs, E rhs)
198{
199 typedef std::underlying_type_t<E> underlying;
200 lhs = static_cast<E> (static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
201 return lhs;
202}
203
204
206template <class E>
207constexpr
208std::enable_if_t<is_bitmask_v<E>, E&>
209operator^= (E& lhs, E rhs)
210{
211 typedef std::underlying_type_t<E> underlying;
212 lhs = static_cast<E> (static_cast<underlying>(lhs) ^ static_cast<underlying>(rhs));
213 return lhs;
214}
215
216
217namespace CxxUtils {
218
219
229template <class E>
230constexpr
231std::enable_if_t<is_bitmask_v<E>, E&>
232set (E& lhs, E rhs)
233{
234 lhs |= rhs;
235 return lhs;
236}
237
238
248template <class E>
249constexpr
250std::enable_if_t<is_bitmask_v<E>, E&>
251reset (E& lhs, E rhs)
252{
253 lhs &= ~rhs;
254 return lhs;
255}
256
257
267template <class E>
268constexpr
269std::enable_if_t<is_bitmask_v<E>, bool>
270test (E lhs, E rhs)
271{
272 typedef std::underlying_type_t<E>underlying;
273 return static_cast<underlying> (lhs & rhs) != 0;
274}
275
276
277} // namespace CxxUtils
278
279
280#endif // not CXXUTILS_BITMASK_H
#define F(x, y, z)
Definition MD5.cxx:112
constexpr std::enable_if_t< is_bitmask_v< E >, E & > operator&=(E &lhs, E rhs)
operator&=
Definition bitmask.h:185
constexpr std::enable_if_t< is_bitmask_v< E >, E & > operator^=(E &lhs, E rhs)
operator^=
Definition bitmask.h:209
constexpr std::enable_if_t< is_bitmask_v< E >, E & > operator|=(E &lhs, E rhs)
operator|=
Definition bitmask.h:197
constexpr std::enable_if_t< is_bitmask_v< E >, E > operator~(E lhs)
operator~
Definition bitmask.h:132
constexpr std::enable_if_t< is_bitmask_v< E >, bool > test(E lhs, E rhs)
Convenience function to test bits in a class enum bitmask.
Definition bitmask.h:270
constexpr std::enable_if_t< is_bitmask_v< E >, E & > reset(E &lhs, E rhs)
Convenience function to clear bits in a class enum bitmask.
Definition bitmask.h:251
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition bitmask.h:232