|
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...
|
|
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.