ATLAS Offline Software
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  */
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 
74 namespace {
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 
129 template <class E>
130 constexpr
131 std::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 
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)
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 
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)
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 
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)
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 
182 template <class E>
183 constexpr
184 std::enable_if_t<is_bitmask_v<E>, E&>
185 operator&= (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 
194 template <class E>
195 constexpr
196 std::enable_if_t<is_bitmask_v<E>, E&>
197 operator|= (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 
206 template <class E>
207 constexpr
208 std::enable_if_t<is_bitmask_v<E>, E&>
209 operator^= (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 
217 namespace CxxUtils {
218 
219 
229 template <class E>
230 constexpr
231 std::enable_if_t<is_bitmask_v<E>, E&>
232 set (E& lhs, E rhs)
233 {
234  lhs |= rhs;
235  return lhs;
236 }
237 
238 
248 template <class E>
249 constexpr
250 std::enable_if_t<is_bitmask_v<E>, E&>
251 reset (E& lhs, E rhs)
252 {
253  lhs &= ~rhs;
254  return lhs;
255 }
256 
257 
267 template <class E>
268 constexpr
269 std::enable_if_t<is_bitmask_v<E>, bool>
270 test (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
CxxUtils
Definition: aligned_vector.h:29
operator^=
constexpr std::enable_if_t< is_bitmask_v< E >, E & > operator^=(E &lhs, E rhs)
operator^=
Definition: bitmask.h:209
CxxUtils::set
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
CxxUtils::test
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
VP1PartSpect::E
@ E
Definition: VP1PartSpectFlags.h:21
operator|=
constexpr std::enable_if_t< is_bitmask_v< E >, E & > operator|=(E &lhs, E rhs)
operator|=
Definition: bitmask.h:197
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
F
#define F(x, y, z)
Definition: MD5.cxx:112
CxxUtils::reset
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
operator&=
constexpr std::enable_if_t< is_bitmask_v< E >, E & > operator&=(E &lhs, E rhs)
operator&=
Definition: bitmask.h:185
TSU::T
unsigned long long T
Definition: L1TopoDataTypes.h:35
operator~
constexpr std::enable_if_t< is_bitmask_v< E >, E > operator~(E lhs)
operator~
Definition: bitmask.h:132