| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- #pragma once
- #include <compare>
- /**
- * @brief Generator-macro for creating instant tri-bools, a boolean-like type
- * that has a "True" state, a "False" state, and a "Maybe"/"Indeterminate"
- * state. {@see boost::tribool} for an example of this functionality.
- *
- * TriBool types obey the following rules of behavior (with T := True,
- * F := False, M := Maybe):
- *
- * Unary operators operate as follows:
- * | op \ in | T | F | M |
- * |---------|---|---|---|
- * | bool() | T | F | T |
- * | ! | F | T | M |
- * |---------|---|---|---|
- *
- * AND operates as follows:
- * | | T | F | M |
- * |---|---|---|---|
- * | T | T | F | T |
- * | F | F | F | F |
- * | M | T | F | M |
- * |---|---|---|---|
- *
- * OR operates as follows:
- * | | T | F | M |
- * |---|---|---|---|
- * | T | T | T | T |
- * | F | T | F | M |
- * | M | T | M | M |
- * |---|---|---|---|
- *
- * @param TypeName the name of the class being declared
- * @param True the name of the truthy enumeration
- * @param False the name of the falsy enumeration
- * @param Maybe the name of the indeterminate enumeration
- */
- #define JVALIDATE_TRIBOOL_TYPE(TypeName, True, False, Maybe) \
- class TypeName { \
- public: \
- enum Enum { True, False, Maybe }; \
- \
- private: \
- Enum state_; \
- \
- public: \
- /* Translate a boolean into a tribool value, will never be Maybe */ \
- constexpr TypeName(bool state) : state_(state ? True : False) {} \
- constexpr TypeName(Enum state) : state_(state) {} \
- \
- /* Convert to enum for use in switch() statements */ \
- constexpr Enum operator*() const { return state_; } \
- /* Convert to bool for use in if()/while() statements, requires static_cast otherwise */ \
- constexpr explicit operator bool() const { return state_ != False; } \
- \
- /* Inverts the tribool's value if it is already a concrete boolean type */ \
- friend constexpr TypeName operator!(TypeName val) { \
- if (val.state_ == Maybe) { \
- return Maybe; \
- } \
- return val.state_ == False ? True : False; \
- } \
- \
- /* Combines two tribools as if performing boolean-OR */ \
- friend constexpr TypeName operator|(TypeName lhs, TypeName rhs) { \
- if (lhs.state_ == True || rhs.state_ == True) { \
- return True; \
- } \
- if (lhs.state_ == Maybe || rhs.state_ == Maybe) { \
- return Maybe; \
- } \
- return False; \
- } \
- \
- /* Combines two tribools as if performing boolean-AND */ \
- friend constexpr TypeName operator&(TypeName lhs, TypeName rhs) { \
- if (lhs.state_ == False || rhs.state_ == False) { \
- return False; \
- } \
- if (lhs.state_ == Maybe && rhs.state_ == Maybe) { \
- return Maybe; \
- } \
- return True; \
- } \
- \
- constexpr TypeName & operator&=(TypeName rhs) { return *this = *this & rhs; } \
- constexpr TypeName & operator|=(TypeName rhs) { return *this = *this | rhs; } \
- \
- friend constexpr auto operator==(TypeName lhs, TypeName::Enum rhs) { \
- return static_cast<int>(lhs.state_) == static_cast<int>(rhs); \
- } \
- friend constexpr auto operator!=(TypeName lhs, TypeName::Enum rhs) { \
- return static_cast<int>(lhs.state_) != static_cast<int>(rhs); \
- } \
- friend constexpr auto operator<=>(TypeName lhs, TypeName rhs) { \
- return static_cast<int>(lhs.state_) <=> static_cast<int>(rhs.state_); \
- } \
- }
|