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 139 of file bitmask.h.

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 }

◆ operator&=()

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

operator&=

Definition at line 177 of file bitmask.h.

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 }

◆ 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 165 of file bitmask.h.

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 }

◆ operator^=()

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

operator^=

Definition at line 201 of file bitmask.h.

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 }

◆ 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 152 of file bitmask.h.

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 }

◆ operator|=()

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

operator|=

Definition at line 189 of file bitmask.h.

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 }

◆ operator~()

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

operator~

Definition at line 124 of file bitmask.h.

125 {
126  typedef std::underlying_type_t<E> underlying;
127  return static_cast<E> (~static_cast<underlying>(lhs));
128 }
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