Created
March 16, 2018 22:55
-
-
Save mciantyre/cdf0b8e1e74a5ad2cf8d8914938e0ea0 to your computer and use it in GitHub Desktop.
Code: Safer configuration and exception masks in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdint> | |
enum class ValidationExceptions : uint32_t | |
{ | |
COMP_NO_EXCEPTION = 0, | |
COMP_DIV_BY_ZERO = 1, | |
COMP_EXCEEDS_MIN = 2, | |
COMP_EXCEEDS_MAX = 4, | |
COMP_NOT_ENOUGH = 8, | |
}; | |
template <typename Flag> | |
struct Mask | |
{ | |
using This = Mask<Flag>; | |
uint32_t mask; | |
/* 1 */ constexpr Mask() : mask(0) {} | |
/* 2 */ constexpr Mask(Flag flag) : mask(static_cast<uint32_t>(flag)) {} | |
constexpr This& operator|=(This that) | |
{ | |
this->mask |= that.mask; | |
return *this; | |
} | |
constexpr This& operator&=(This that) | |
{ | |
this->mask &= that.mask; | |
return *this; | |
} | |
friend constexpr const This operator|(This lhs, This rhs) | |
{ | |
lhs |= rhs; | |
return lhs; | |
} | |
friend constexpr const This operator&(This lhs, This rhs) | |
{ | |
lhs &= rhs; | |
return lhs; | |
} | |
explicit operator bool() const { return mask > 0; } | |
}; | |
using ValidationMask = Mask<ValidationExceptions>; | |
static_assert( | |
(ValidationMask(ValidationExceptions::COMP_NOT_ENOUGH) | ValidationExceptions::COMP_DIV_BY_ZERO).mask == (static_cast<uint32_t>(ValidationExceptions::COMP_NOT_ENOUGH) | static_cast<uint32_t>(ValidationExceptions::COMP_DIV_BY_ZERO)), | |
"Failed to OR mask and flag" | |
); | |
static_assert( | |
(ValidationMask(ValidationExceptions::COMP_NOT_ENOUGH) & ValidationExceptions::COMP_DIV_BY_ZERO).mask == (static_cast<uint32_t>(ValidationExceptions::COMP_NOT_ENOUGH) & static_cast<uint32_t>(ValidationExceptions::COMP_DIV_BY_ZERO)), | |
"Failed to AND mask and flag" | |
); | |
int main(int argc, const char * argv[]) { | |
int denom = 0; | |
ValidationMask mask; | |
if (0 == denom) | |
{ | |
mask |= ValidationExceptions::COMP_DIV_BY_ZERO; | |
} | |
ValidationMask anotherMask(ValidationExceptions::COMP_NOT_ENOUGH); | |
mask &= anotherMask; | |
if (mask & ValidationExceptions::COMP_DIV_BY_ZERO) | |
{ | |
// Log an exception | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment