@@ -12,18 +12,103 @@ namespace debug {
1212
1313// / @brief Used to compare two sizes at compile time.
1414// / Typically this will force a compiler to evaluate the expression at compile time. Used in place of the availability of consteval.
15+ // / @tparam A The first value to compare
16+ // / @tparam B The second value to compare
17+ // / @code
18+ // / using Check = ConstexprValueCompare<sizeof(MyType), 4>;
19+ // / @endcode
1520template <std::size_t A, std::size_t B>
1621class ConstexprValueCompare final {
1722public:
1823 static_assert (A == B, " Values must match!" );
24+ static constexpr bool value = true ; // for SFINAE purposes
1925};
2026
2127// / @brief Used to compare two values at compile time to see if A is evenly divisible by B.
22- // / Typically this will force a compiler to evaluate the expression at compile time. Used in place of the availability of consteval.
28+ // / Use in a manner to force a compiler to evaluate the expression at compile time.
29+ // / @tparam A The first value to compare
30+ // / @tparam B The second value to compare
2331template <std::size_t A, std::size_t B>
2432class ConstexprValueDivisible final {
2533public:
2634 static_assert ((A % B) == 0 , " Second value must evenly divide first value!" );
35+ static constexpr bool value = true ; // for SFINAE purposes
36+ };
37+
38+ // / @brief Used to compare two values at compile time to see if A is less than B.
39+ // / Use in a manner to force a compiler to evaluate the expression at compile time.
40+ // / @tparam A The first value to compare
41+ // / @tparam B The second value to compare
42+ template <std::size_t A, std::size_t B>
43+ class ConstexprValueLessThan final {
44+ public:
45+ static_assert (A < B, " First value must be less than second value!" );
46+ static constexpr bool value = true ; // for SFINAE purposes
47+ };
48+
49+ // / @brief Used to compare two values at compile time to see if A is less than or equal to B.
50+ // / Use in a manner to force a compiler to evaluate the expression at compile time.
51+ // / @tparam A The first value to compare
52+ // / @tparam B The second value to compare
53+ template <std::size_t A, std::size_t B>
54+ class ConstexprValueLessEqual final {
55+ public:
56+ static_assert (A <= B, " First value must be less than or equal to second value!" );
57+ static constexpr bool value = true ; // for SFINAE purposes
58+ };
59+
60+ // / @brief Used to determine if a value is a power of two at compile time.
61+ // / Use in a manner to force a compiler to evaluate the expression at compile time.
62+ // / @tparam N The value to check if it is a power of two
63+ template <std::size_t N>
64+ class ConstexprIsPowerOfTwo final {
65+ public:
66+ static_assert (N > 0 && (N & (N - 1 )) == 0 , " Value must be a power of two!" );
67+ static constexpr bool value = true ; // for SFINAE purposes
68+ };
69+
70+ // / @brief Used to determine if a value is within a specified range at compile time.
71+ // / Use in a manner to force a compiler to evaluate the expression at compile time.
72+ // / @tparam Value The value to check if it is within the range
73+ // / @tparam Min The minimum value of the range (inclusive)
74+ // / @tparam Max The maximum value of the range (inclusive)
75+ template <std::size_t Value, std::size_t Min, std::size_t Max>
76+ class ConstexprValueInRange final {
77+ public:
78+ static_assert (Value >= Min && Value <= Max, " Value must be within specified range!" );
79+ static constexpr bool value = true ; // for SFINAE purposes
80+ };
81+
82+ // / @brief Force a compile error showing the type T
83+ // / @tparam T The type to show in the compile error
84+ // / Usage: TypeDebugger<decltype(my_var)> show_type;
85+ template <typename T>
86+ class TypeDebugger ; // Intentionally no definition - will cause compile error showing T
87+
88+ // / @brief Show size of a type at compile time (will fail, but show size in error)
89+ // / @tparam T The type to show the size of
90+ // / Usage: TypeSizeDebugger<my_type> show_size;
91+ template <typename T, std::size_t Size = sizeof (T)>
92+ class TypeSizeDebugger ; // Intentionally no definition
93+
94+ // / @brief Verify type sizes match expectations
95+ // / @tparam T The type to check the size of
96+ // / @tparam ExpectedSize The expected size of the type in bytes
97+ template <typename T, std::size_t ExpectedSize>
98+ class TypeSizeValidator final {
99+ public:
100+ static_assert (sizeof (T) == ExpectedSize, " Type size does not match expected size!" );
101+ static constexpr std::size_t value = sizeof (T);
102+ };
103+
104+ // / @brief Verify type alignment matches expectations
105+ // / @tparam T The type to check the alignment of
106+ // / @tparam ExpectedAlignment The expected alignment of the type in bytes
107+ template <typename T, std::size_t ExpectedAlignment>
108+ class TypeAlignmentValidator final {
109+ public:
110+ static_assert (alignof (T) == ExpectedAlignment, " Type alignment does not match expected alignment!" );
111+ static constexpr std::size_t value = alignof (T);
27112};
28113
29114// / The type used to store debug masks.
@@ -107,18 +192,35 @@ enum class MaskType : StorageType {
107192 All = ~0U , // /< Used to indicate that the message will be grouped with All operations.
108193};
109194
195+ // / @brief Bitwise operators for MaskType to allow for easy combination and checking of masks.
196+ // / @param lhs The left-hand side of the bitwise operation, which is a StorageType value.
197+ // / @param rhs The right-hand side of the bitwise operation, which is a MaskType
198+ // / @return A boolean value indicating whether the bitwise AND of the StorageType and MaskType is non-zero.
110199constexpr bool operator &(StorageType lhs, MaskType rhs) {
111200 return (lhs & static_cast <StorageType>(rhs)) != 0 ;
112201}
202+
203+ // / @brief Bitwise operators for MaskType to allow for easy combination and checking of masks.
204+ // / @param lhs The left-hand side of the bitwise operation, which is a MaskType value.
205+ // / @param rhs The right-hand side of the bitwise operation, which is a StorageType value.
206+ // / @return A boolean value indicating whether the bitwise AND of the MaskType and StorageType is non-zero.
113207constexpr bool operator &(MaskType lhs, StorageType rhs) {
114208 return (static_cast <StorageType>(lhs) & rhs) != 0 ;
115209}
210+
211+ // / @brief Bitwise operators for MaskType to allow for easy combination of MaskType values.
212+ // / @param lhs The left-hand side of the bitwise operation, which is a MaskType value.
213+ // / @param rhs The right-hand side of the bitwise operation, which is a MaskType value.
214+ // / @return A MaskType value that is the result of the bitwise OR of the two MaskType values. This "value" WILL NO LONGER be a valid MaskType, but can
215+ // / be used to nest further bitwise operations to combine multiple MaskType values together.
116216constexpr MaskType operator |(MaskType lhs, MaskType rhs) {
117217 return static_cast <MaskType>(static_cast <StorageType>(lhs) | static_cast <StorageType>(rhs));
118218}
119219
120220#if not defined(DEBUG_MASK)
121- #define DEBUG_MASK static_cast <StorageType>(0x7ULL )
221+ // / @brief The mask used to determine which debug messages are enabled. This should be defined by the user before including this header.
222+ // / The default value does not enable all messages.
223+ #define DEBUG_MASK static_cast <StorageType>(0x0000'0002'0000'0007ULL )
122224#endif
123225
124226constexpr static bool Fatal{DEBUG_MASK & MaskType::Fatal};
0 commit comments