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-2023 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  template <class E>
107  constexpr bool is_bitmask_v<E, std::enable_if_t<(E::IS_ATH_BITMASK,1)>> = true;
108 }
109 
110 
111 /*
112  * Define bitwise operators for class enums.
113  * These all cast the operands to the underlying type, and then cast
114  * the result back again to the enumeration.
115  *
116  * These functions are enabled only for enumerators that have used the
117  * @c ATH_BITMASK macro.
118  */
119 
121 template <class E>
122 constexpr
123 std::enable_if_t<is_bitmask_v<E>, E>
125 {
126  typedef std::underlying_type_t<E> underlying;
127  return static_cast<E> (~static_cast<underlying>(lhs));
128 }
129 
130 
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)
140 {
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));
144 }
145 
146 
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)
153 {
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));
157 }
158 
159 
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)
166 {
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));
170 }
171 
172 
174 template <class E>
175 constexpr
176 std::enable_if_t<is_bitmask_v<E>, E&>
177 operator&= (E& lhs, E rhs)
178 {
179  typedef std::underlying_type_t<E> underlying;
180  lhs = static_cast<E> (static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
181  return lhs;
182 }
183 
184 
186 template <class E>
187 constexpr
188 std::enable_if_t<is_bitmask_v<E>, E&>
189 operator|= (E& lhs, E rhs)
190 {
191  typedef std::underlying_type_t<E> underlying;
192  lhs = static_cast<E> (static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
193  return lhs;
194 }
195 
196 
198 template <class E>
199 constexpr
200 std::enable_if_t<is_bitmask_v<E>, E&>
201 operator^= (E& lhs, E rhs)
202 {
203  typedef std::underlying_type_t<E> underlying;
204  lhs = static_cast<E> (static_cast<underlying>(lhs) ^ static_cast<underlying>(rhs));
205  return lhs;
206 }
207 
208 
209 namespace CxxUtils {
210 
211 
221 template <class E>
222 constexpr
223 std::enable_if_t<is_bitmask_v<E>, E&>
224 set (E& lhs, E rhs)
225 {
226  lhs |= rhs;
227  return lhs;
228 }
229 
230 
240 template <class E>
241 constexpr
242 std::enable_if_t<is_bitmask_v<E>, E&>
243 reset (E& lhs, E rhs)
244 {
245  lhs &= ~rhs;
246  return lhs;
247 }
248 
249 
259 template <class E>
260 constexpr
261 std::enable_if_t<is_bitmask_v<E>, bool>
262 test (E lhs, E rhs)
263 {
264  typedef std::underlying_type_t<E>underlying;
265  return static_cast<underlying> (lhs & rhs) != 0;
266 }
267 
268 
269 } // namespace CxxUtils
270 
271 
272 #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:201
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:224
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:262
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:189
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:243
operator&=
constexpr std::enable_if_t< is_bitmask_v< E >, E & > operator&=(E &lhs, E rhs)
operator&=
Definition: bitmask.h:177
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:124