ATLAS Offline Software
Namespaces | Macros | Functions
bitmask.h File Reference

Helpers for treating a class enum as a bitmask. More...

#include <type_traits>
Include dependency graph for bitmask.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Namespaces

 CxxUtils
 

Macros

#define ATH_BITMASK   IS_ATH_BITMASK=1
 Mark that a class enum should be treated as a bitmask. More...
 

Functions

template<class E >
constexpr std::enable_if_t< is_bitmask_v< E >, E > operator~ (E lhs)
 operator~ More...
 
template<class E , class F , typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) && has_same_underlying_v<E,F>>>
constexpr auto operator& (E lhs, F rhs)
 operator& More...
 
template<class E , class F , typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) && has_same_underlying_v<E,F>>>
constexpr auto operator| (E lhs, F rhs)
 operator| More...
 
template<class E , class F , typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) && has_same_underlying_v<E,F>>>
constexpr auto operator^ (E lhs, F rhs)
 operator^ More...
 
template<class E >
constexpr std::enable_if_t< is_bitmask_v< E >, E & > operator&= (E &lhs, E rhs)
 operator&= More...
 
template<class E >
constexpr std::enable_if_t< is_bitmask_v< E >, E & > operator|= (E &lhs, E rhs)
 operator|= More...
 
template<class E >
constexpr std::enable_if_t< is_bitmask_v< E >, E & > operator^= (E &lhs, E rhs)
 operator^= More...
 
template<class E >
constexpr std::enable_if_t< is_bitmask_v< E >, E & > CxxUtils::set (E &lhs, E rhs)
 Convenience function to set bits in a class enum bitmask. More...
 
template<class E >
constexpr std::enable_if_t< is_bitmask_v< E >, E & > CxxUtils::reset (E &lhs, E rhs)
 Convenience function to clear bits in a class enum bitmask. More...
 
template<class E >
constexpr std::enable_if_t< is_bitmask_v< E >, bool > CxxUtils::test (E lhs, E rhs)
 Convenience function to test bits in a class enum bitmask. More...
 

Detailed Description

Helpers for treating a class enum as a bitmask.

Author
scott snyder snyde.nosp@m.r@bn.nosp@m.l.gov
Date
Mar, 2018 C++11 class enums are very nice from a type-safety viewpoint. However, they are a bit awkward if you want to use them to represent a bitmask. For example:
enum class Mask { Bit0 = 1, Bit1 = 2, Bit2 = 4 };
Mask m = Mask::Bit1 | Mask::Bit2;
doesn't compile because the enumerators are not convertible to integers. One can cast back and forth between the enum and integers, but that's awkward to do everywhere.

This header defines overloads for the bitwise operators that work with a class enum. To enable these overloads, you need to add the ATH_BITMASK macro at the end of your enum declaration:

enum class Mask { Bit0 = 1, Bit1 = 2, Bit2 = 4,

After that, the usual bitwise operations (&, |, ^, &=, |=, ^=, ~) should work as expected. There are also a few convenience functions defined in the CxxUtils namespace: set, reset, and test.

In case of two different enum types (with common underlying type) the (non-assignment) boolean operators (&, |, ^) are also defined:

int result = Mask::Bit1 & OtherMask::Bit2

This approach was suggested by these postings:

http://blog.bitwigglers.org/using-enum-classes-as-type-safe-bitmasks https://www.justsoftwaresolutions.co.uk/cplusplus/using-enum-classes-as-bitfields.html

except that we rely on injecting a known enumerator into the type rather than using a separate traits class. This way works better if the enumeration is defined in a nested scope.

Definition in file bitmask.h.

Macro Definition Documentation

◆ ATH_BITMASK

#define ATH_BITMASK   IS_ATH_BITMASK=1

Mark that a class enum should be treated as a bitmask.

Put this at the end of the enumeration, after a comma, like this:

enum class Mask { Bit0 = 1, Bit1 = 2, Bit2 = 4,

Definition at line 71 of file bitmask.h.

Function Documentation

◆ operator&()

template<class E , class F , typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) && has_same_underlying_v<E,F>>>
constexpr auto operator& ( lhs,
F  rhs 
)
constexpr

operator&

One operand needs to be a bitmask and the other share at least the same underlying type. This allows bit operations with the underlying type (e.g. int) and chained operations involving more than two bitmasks.

Definition at line 147 of file bitmask.h.

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 }

◆ operator&=()

template<class E >
constexpr std::enable_if_t<is_bitmask_v<E>, E&> operator&= ( E &  lhs,
rhs 
)
constexpr

operator&=

Definition at line 185 of file bitmask.h.

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 }

◆ operator^()

template<class E , class F , typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) && has_same_underlying_v<E,F>>>
constexpr auto operator^ ( lhs,
F  rhs 
)
constexpr

operator^

Definition at line 173 of file bitmask.h.

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 }

◆ operator^=()

template<class E >
constexpr std::enable_if_t<is_bitmask_v<E>, E&> operator^= ( E &  lhs,
rhs 
)
constexpr

operator^=

Definition at line 209 of file bitmask.h.

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 }

◆ operator|()

template<class E , class F , typename = std::enable_if_t<(is_bitmask_v<E> || is_bitmask_v<F>) && has_same_underlying_v<E,F>>>
constexpr auto operator| ( lhs,
F  rhs 
)
constexpr

operator|

Definition at line 160 of file bitmask.h.

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 }

◆ operator|=()

template<class E >
constexpr std::enable_if_t<is_bitmask_v<E>, E&> operator|= ( E &  lhs,
rhs 
)
constexpr

operator|=

Definition at line 197 of file bitmask.h.

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 }

◆ operator~()

template<class E >
constexpr std::enable_if_t<is_bitmask_v<E>, E> operator~ ( lhs)
constexpr

operator~

Definition at line 132 of file bitmask.h.

133 {
134  typedef std::underlying_type_t<E> underlying;
135  return static_cast<E> (~static_cast<underlying>(lhs));
136 }
ATH_BITMASK
#define ATH_BITMASK
Mark that a class enum should be treated as a bitmask.
Definition: bitmask.h:70
get_generator_info.result
result
Definition: get_generator_info.py:21
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
VP1PartSpect::E
@ E
Definition: VP1PartSpectFlags.h:21