mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 22:02:44 +00:00 
			
		
		
		
	AK+Everywhere: Replace DistinctNumeric bool parameters with named ones
This means that rather than this:
```
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false,
    false, true, FunctionAddress);
```
We now have this:
```
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, FunctionAddress, Arithmetic,
    Comparison, Increment);
```
Which is a lot more readable. :^)
Co-authored-by: Ali Mohammad Pur <mpfard@serenityos.org>
			
			
This commit is contained in:
		
							parent
							
								
									24c0a6e9a4
								
							
						
					
					
						commit
						c33eae24f9
					
				
					 7 changed files with 133 additions and 92 deletions
				
			
		|  | @ -113,13 +113,12 @@ struct ArbitrarySizedEnum : public T { | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define AK_MAKE_ARBITRARY_SIZED_ENUM(EnumName, T, ...)                               \ | #define AK_MAKE_ARBITRARY_SIZED_ENUM(EnumName, T, ...)                                                                         \ | ||||||
|     namespace EnumName {                                                             \ |     namespace EnumName {                                                                                                       \ | ||||||
|     using EnumName = ArbitrarySizedEnum<DistinctNumeric<T, struct __##EnumName##Tag, \ |     using EnumName = ArbitrarySizedEnum<DistinctNumeric<T, struct __##EnumName##Tag, AK::DistinctNumericFeature::Comparison>>; \ | ||||||
|         false, true, false, false, false, false>>;                                   \ |     using Type = EnumName;                                                                                                     \ | ||||||
|     using Type = EnumName;                                                           \ |     using UnderlyingType = T;                                                                                                  \ | ||||||
|     using UnderlyingType = T;                                                        \ |     inline constexpr static EnumName __VA_ARGS__;                                                                              \ | ||||||
|     inline constexpr static EnumName __VA_ARGS__;                                    \ |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2020, Ben Wiederhake <BenWiederhake.GitHub@gmx.de> |  * Copyright (c) 2020, Ben Wiederhake <BenWiederhake.GitHub@gmx.de> | ||||||
|  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> |  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> | ||||||
|  |  * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
|  | @ -19,20 +20,19 @@ namespace AK { | ||||||
|  * want simply gets different values for `fn_length` and `line`. The macros |  * want simply gets different values for `fn_length` and `line`. The macros | ||||||
|  * `TYPEDEF_DISTINCT_NUMERIC_*()` at the bottom of `DistinctNumeric.h`. |  * `TYPEDEF_DISTINCT_NUMERIC_*()` at the bottom of `DistinctNumeric.h`. | ||||||
|  * |  * | ||||||
|  * `Incr`, `Cmp`, `Bool`, `Flags`, `Shift`, and `Arith` simply split up the |  * The tags in `DistinctNumericFeature` simply split up the space of operators into 6 simple categories: | ||||||
|  * space of operators into 6 simple categories: |  | ||||||
|  * - No matter the values of these, `DistinctNumeric` always implements `==` and `!=`. |  * - No matter the values of these, `DistinctNumeric` always implements `==` and `!=`. | ||||||
|  * - If `Incr` is true, then `++a`, `a++`, `--a`, and `a--` are implemented. |  * - If `Arithmetic` is present, then `a+b`, `a-b`, `+a`, `-a`, `a*b`, `a/b`, `a%b`, and the respective `a_=b` versions are implemented. | ||||||
|  * - If `Cmp` is true, then `a>b`, `a<b`, `a>=b`, and `a<=b` are implemented. |  * - If `CastToBool` is present, then `!a`, `a&&b`, and `a||b` are implemented (but not `operator bool()`, because of overzealous integer promotion rules). | ||||||
|  * - If `Bool` is true, then `!a`, `a&&b`, and `a||b` are implemented (but not `operator bool()`, because of overzealous integer promotion rules). |  * - If `Comparison` is present, then `a>b`, `a<b`, `a>=b`, and `a<=b` are implemented. | ||||||
|  * - If `Flags` is true, then `~a`, `a&b`, `a|b`, `a^b`, `a&=b`, `a|=b`, and `a^=b` are implemented. |  * - If `Flags` is present, then `~a`, `a&b`, `a|b`, `a^b`, `a&=b`, `a|=b`, and `a^=b` are implemented. | ||||||
|  * - If `Shift` is true, then `a<<b`, `a>>b`, `a<<=b`, `a>>=b` are implemented. |  * - If `Increment` is present, then `++a`, `a++`, `--a`, and `a--` are implemented. | ||||||
|  * - If `Arith` is true, then `a+b`, `a-b`, `+a`, `-a`, `a*b`, `a/b`, `a%b`, and the respective `a_=b` versions are implemented. |  * - If `Shift` is present, then `a<<b`, `a>>b`, `a<<=b`, `a>>=b` are implemented. | ||||||
|  * The semantics are always those of the underlying basic type `T`. |  * The semantics are always those of the underlying basic type `T`. | ||||||
|  * |  * | ||||||
|  * These can be combined arbitrarily. Want a numeric type that supports `++a` |  * These can be combined arbitrarily. Want a numeric type that supports `++a` | ||||||
|  * and `a >> b` but not `a > b`? Sure thing, just set |  * and `a >> b` but not `a > b`? Sure thing, just set | ||||||
|  * `Incr=true, Cmp=false, Shift=true` and you're done! |  * `Increment, Comparison, Shift` and you're done! | ||||||
|  * Furthermore, some of these overloads make more sense with specific types, like `a&&b` which should be able to operate |  * Furthermore, some of these overloads make more sense with specific types, like `a&&b` which should be able to operate | ||||||
|  * |  * | ||||||
|  * I intentionally decided against overloading `&a` because these shall remain |  * I intentionally decided against overloading `&a` because these shall remain | ||||||
|  | @ -47,9 +47,46 @@ namespace AK { | ||||||
|  * There are many more operators that do not make sense for numerical types, |  * There are many more operators that do not make sense for numerical types, | ||||||
|  * or cannot be overloaded in the first place. Naturally, they are not implemented. |  * or cannot be overloaded in the first place. Naturally, they are not implemented. | ||||||
|  */ |  */ | ||||||
| template<typename T, typename X, bool Incr, bool Cmp, bool Bool, bool Flags, bool Shift, bool Arith> | 
 | ||||||
|  | namespace DistinctNumericFeature { | ||||||
|  | enum Arithmetic {}; | ||||||
|  | enum CastToBool {}; | ||||||
|  | enum Comparison {}; | ||||||
|  | enum Flags {}; | ||||||
|  | enum Increment {}; | ||||||
|  | enum Shift {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | template<typename T, typename X, typename... Opts> | ||||||
| class DistinctNumeric { | class DistinctNumeric { | ||||||
|     using Self = DistinctNumeric<T, X, Incr, Cmp, Bool, Flags, Shift, Arith>; |     using Self = DistinctNumeric<T, X, Opts...>; | ||||||
|  | 
 | ||||||
|  |     struct Option { | ||||||
|  |         template<typename K, typename... Os> | ||||||
|  |         consteval Option(K option, Os... other_options) | ||||||
|  |             : Option(other_options...) | ||||||
|  |         { | ||||||
|  |             set(option); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         consteval Option() { } | ||||||
|  | 
 | ||||||
|  |         constexpr void set(DistinctNumericFeature::Arithmetic const&) { arithmetic = true; } | ||||||
|  |         constexpr void set(DistinctNumericFeature::CastToBool const&) { cast_to_bool = true; } | ||||||
|  |         constexpr void set(DistinctNumericFeature::Comparison const&) { comparisons = true; } | ||||||
|  |         constexpr void set(DistinctNumericFeature::Flags const&) { flags = true; } | ||||||
|  |         constexpr void set(DistinctNumericFeature::Increment const&) { increment = true; } | ||||||
|  |         constexpr void set(DistinctNumericFeature::Shift const&) { shift = true; } | ||||||
|  | 
 | ||||||
|  |         bool arithmetic { false }; | ||||||
|  |         bool cast_to_bool { false }; | ||||||
|  |         bool comparisons { false }; | ||||||
|  |         bool flags { false }; | ||||||
|  |         bool increment { false }; | ||||||
|  |         bool shift { false }; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     constexpr static Option options { Opts()... }; | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     constexpr DistinctNumeric() = default; |     constexpr DistinctNumeric() = default; | ||||||
|  | @ -59,7 +96,7 @@ public: | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     constexpr const T& value() const { return m_value; } |     constexpr T const& value() const { return m_value; } | ||||||
|     constexpr T& value() { return m_value; } |     constexpr T& value() { return m_value; } | ||||||
| 
 | 
 | ||||||
|     // Always implemented: identity.
 |     // Always implemented: identity.
 | ||||||
|  | @ -68,61 +105,61 @@ public: | ||||||
|         return this->m_value == other.m_value; |         return this->m_value == other.m_value; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Only implemented when `Incr` is true:
 |     // Only implemented when `Increment` is true:
 | ||||||
|     constexpr Self& operator++() |     constexpr Self& operator++() | ||||||
|     { |     { | ||||||
|         static_assert(Incr, "'++a' is only available for DistinctNumeric types with 'Incr'."); |         static_assert(options.increment, "'++a' is only available for DistinctNumeric types with 'Increment'."); | ||||||
|         this->m_value += 1; |         this->m_value += 1; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|     constexpr Self operator++(int) |     constexpr Self operator++(int) | ||||||
|     { |     { | ||||||
|         static_assert(Incr, "'a++' is only available for DistinctNumeric types with 'Incr'."); |         static_assert(options.increment, "'a++' is only available for DistinctNumeric types with 'Increment'."); | ||||||
|         Self ret = this->m_value; |         Self ret = this->m_value; | ||||||
|         this->m_value += 1; |         this->m_value += 1; | ||||||
|         return ret; |         return ret; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator--() |     constexpr Self& operator--() | ||||||
|     { |     { | ||||||
|         static_assert(Incr, "'--a' is only available for DistinctNumeric types with 'Incr'."); |         static_assert(options.increment, "'--a' is only available for DistinctNumeric types with 'Increment'."); | ||||||
|         this->m_value -= 1; |         this->m_value -= 1; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|     constexpr Self operator--(int) |     constexpr Self operator--(int) | ||||||
|     { |     { | ||||||
|         static_assert(Incr, "'a--' is only available for DistinctNumeric types with 'Incr'."); |         static_assert(options.increment, "'a--' is only available for DistinctNumeric types with 'Increment'."); | ||||||
|         Self ret = this->m_value; |         Self ret = this->m_value; | ||||||
|         this->m_value -= 1; |         this->m_value -= 1; | ||||||
|         return ret; |         return ret; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Only implemented when `Cmp` is true:
 |     // Only implemented when `Comparison` is true:
 | ||||||
|     constexpr bool operator>(Self const& other) const |     constexpr bool operator>(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Cmp, "'a>b' is only available for DistinctNumeric types with 'Cmp'."); |         static_assert(options.comparisons, "'a>b' is only available for DistinctNumeric types with 'Comparison'."); | ||||||
|         return this->m_value > other.m_value; |         return this->m_value > other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr bool operator<(Self const& other) const |     constexpr bool operator<(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Cmp, "'a<b' is only available for DistinctNumeric types with 'Cmp'."); |         static_assert(options.comparisons, "'a<b' is only available for DistinctNumeric types with 'Comparison'."); | ||||||
|         return this->m_value < other.m_value; |         return this->m_value < other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr bool operator>=(Self const& other) const |     constexpr bool operator>=(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Cmp, "'a>=b' is only available for DistinctNumeric types with 'Cmp'."); |         static_assert(options.comparisons, "'a>=b' is only available for DistinctNumeric types with 'Comparison'."); | ||||||
|         return this->m_value >= other.m_value; |         return this->m_value >= other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr bool operator<=(Self const& other) const |     constexpr bool operator<=(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Cmp, "'a<=b' is only available for DistinctNumeric types with 'Cmp'."); |         static_assert(options.comparisons, "'a<=b' is only available for DistinctNumeric types with 'Comparison'."); | ||||||
|         return this->m_value <= other.m_value; |         return this->m_value <= other.m_value; | ||||||
|     } |     } | ||||||
|     // 'operator<=>' cannot be implemented. See class comment.
 |     // 'operator<=>' cannot be implemented. See class comment.
 | ||||||
| 
 | 
 | ||||||
|     // Only implemented when `bool` is true:
 |     // Only implemented when `CastToBool` is true:
 | ||||||
|     constexpr bool operator!() const |     constexpr bool operator!() const | ||||||
|     { |     { | ||||||
|         static_assert(Bool, "'!a' is only available for DistinctNumeric types with 'Bool'."); |         static_assert(options.cast_to_bool, "'!a' is only available for DistinctNumeric types with 'CastToBool'."); | ||||||
|         return !this->m_value; |         return !this->m_value; | ||||||
|     } |     } | ||||||
|     // Intentionally don't define `operator bool() const` here. C++ is a bit
 |     // Intentionally don't define `operator bool() const` here. C++ is a bit
 | ||||||
|  | @ -133,39 +170,39 @@ public: | ||||||
|     // Only implemented when `Flags` is true:
 |     // Only implemented when `Flags` is true:
 | ||||||
|     constexpr Self operator~() const |     constexpr Self operator~() const | ||||||
|     { |     { | ||||||
|         static_assert(Flags, "'~a' is only available for DistinctNumeric types with 'Flags'."); |         static_assert(options.flags, "'~a' is only available for DistinctNumeric types with 'Flags'."); | ||||||
|         return ~this->m_value; |         return ~this->m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self operator&(Self const& other) const |     constexpr Self operator&(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Flags, "'a&b' is only available for DistinctNumeric types with 'Flags'."); |         static_assert(options.flags, "'a&b' is only available for DistinctNumeric types with 'Flags'."); | ||||||
|         return this->m_value & other.m_value; |         return this->m_value & other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self operator|(Self const& other) const |     constexpr Self operator|(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Flags, "'a|b' is only available for DistinctNumeric types with 'Flags'."); |         static_assert(options.flags, "'a|b' is only available for DistinctNumeric types with 'Flags'."); | ||||||
|         return this->m_value | other.m_value; |         return this->m_value | other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self operator^(Self const& other) const |     constexpr Self operator^(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Flags, "'a^b' is only available for DistinctNumeric types with 'Flags'."); |         static_assert(options.flags, "'a^b' is only available for DistinctNumeric types with 'Flags'."); | ||||||
|         return this->m_value ^ other.m_value; |         return this->m_value ^ other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator&=(Self const& other) |     constexpr Self& operator&=(Self const& other) | ||||||
|     { |     { | ||||||
|         static_assert(Flags, "'a&=b' is only available for DistinctNumeric types with 'Flags'."); |         static_assert(options.flags, "'a&=b' is only available for DistinctNumeric types with 'Flags'."); | ||||||
|         this->m_value &= other.m_value; |         this->m_value &= other.m_value; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator|=(Self const& other) |     constexpr Self& operator|=(Self const& other) | ||||||
|     { |     { | ||||||
|         static_assert(Flags, "'a|=b' is only available for DistinctNumeric types with 'Flags'."); |         static_assert(options.flags, "'a|=b' is only available for DistinctNumeric types with 'Flags'."); | ||||||
|         this->m_value |= other.m_value; |         this->m_value |= other.m_value; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator^=(Self const& other) |     constexpr Self& operator^=(Self const& other) | ||||||
|     { |     { | ||||||
|         static_assert(Flags, "'a^=b' is only available for DistinctNumeric types with 'Flags'."); |         static_assert(options.flags, "'a^=b' is only available for DistinctNumeric types with 'Flags'."); | ||||||
|         this->m_value ^= other.m_value; |         this->m_value ^= other.m_value; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|  | @ -174,90 +211,90 @@ public: | ||||||
|     // TODO: Should this take `int` instead?
 |     // TODO: Should this take `int` instead?
 | ||||||
|     constexpr Self operator<<(Self const& other) const |     constexpr Self operator<<(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Shift, "'a<<b' is only available for DistinctNumeric types with 'Shift'."); |         static_assert(options.shift, "'a<<b' is only available for DistinctNumeric types with 'Shift'."); | ||||||
|         return this->m_value << other.m_value; |         return this->m_value << other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self operator>>(Self const& other) const |     constexpr Self operator>>(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Shift, "'a>>b' is only available for DistinctNumeric types with 'Shift'."); |         static_assert(options.shift, "'a>>b' is only available for DistinctNumeric types with 'Shift'."); | ||||||
|         return this->m_value >> other.m_value; |         return this->m_value >> other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator<<=(Self const& other) |     constexpr Self& operator<<=(Self const& other) | ||||||
|     { |     { | ||||||
|         static_assert(Shift, "'a<<=b' is only available for DistinctNumeric types with 'Shift'."); |         static_assert(options.shift, "'a<<=b' is only available for DistinctNumeric types with 'Shift'."); | ||||||
|         this->m_value <<= other.m_value; |         this->m_value <<= other.m_value; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator>>=(Self const& other) |     constexpr Self& operator>>=(Self const& other) | ||||||
|     { |     { | ||||||
|         static_assert(Shift, "'a>>=b' is only available for DistinctNumeric types with 'Shift'."); |         static_assert(options.shift, "'a>>=b' is only available for DistinctNumeric types with 'Shift'."); | ||||||
|         this->m_value >>= other.m_value; |         this->m_value >>= other.m_value; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Only implemented when `Arith` is true:
 |     // Only implemented when `Arithmetic` is true:
 | ||||||
|     constexpr Self operator+(Self const& other) const |     constexpr Self operator+(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'a+b' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'a+b' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         return this->m_value + other.m_value; |         return this->m_value + other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self operator-(Self const& other) const |     constexpr Self operator-(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'a-b' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'a-b' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         return this->m_value - other.m_value; |         return this->m_value - other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self operator+() const |     constexpr Self operator+() const | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'+a' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'+a' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         return +this->m_value; |         return +this->m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self operator-() const |     constexpr Self operator-() const | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'-a' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'-a' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         return -this->m_value; |         return -this->m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self operator*(Self const& other) const |     constexpr Self operator*(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'a*b' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'a*b' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         return this->m_value * other.m_value; |         return this->m_value * other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self operator/(Self const& other) const |     constexpr Self operator/(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'a/b' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'a/b' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         return this->m_value / other.m_value; |         return this->m_value / other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self operator%(Self const& other) const |     constexpr Self operator%(Self const& other) const | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'a%b' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'a%b' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         return this->m_value % other.m_value; |         return this->m_value % other.m_value; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator+=(Self const& other) |     constexpr Self& operator+=(Self const& other) | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'a+=b' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'a+=b' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         this->m_value += other.m_value; |         this->m_value += other.m_value; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator-=(Self const& other) |     constexpr Self& operator-=(Self const& other) | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'a+=b' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'a+=b' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         this->m_value += other.m_value; |         this->m_value += other.m_value; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator*=(Self const& other) |     constexpr Self& operator*=(Self const& other) | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'a*=b' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'a*=b' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         this->m_value *= other.m_value; |         this->m_value *= other.m_value; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator/=(Self const& other) |     constexpr Self& operator/=(Self const& other) | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'a/=b' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'a/=b' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         this->m_value /= other.m_value; |         this->m_value /= other.m_value; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|     constexpr Self& operator%=(Self const& other) |     constexpr Self& operator%=(Self const& other) | ||||||
|     { |     { | ||||||
|         static_assert(Arith, "'a%=b' is only available for DistinctNumeric types with 'Arith'."); |         static_assert(options.arithmetic, "'a%=b' is only available for DistinctNumeric types with 'Arithmetic'."); | ||||||
|         this->m_value %= other.m_value; |         this->m_value %= other.m_value; | ||||||
|         return *this; |         return *this; | ||||||
|     } |     } | ||||||
|  | @ -266,29 +303,34 @@ private: | ||||||
|     T m_value {}; |     T m_value {}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template<typename T, typename X, bool Incr, bool Cmp, bool Bool, bool Flags, bool Shift, bool Arith> | template<typename T, typename X, typename... Opts> | ||||||
| struct Formatter<DistinctNumeric<T, X, Incr, Cmp, Bool, Flags, Shift, Arith>> : Formatter<T> { | struct Formatter<DistinctNumeric<T, X, Opts...>> : Formatter<T> { | ||||||
|     ErrorOr<void> format(FormatBuilder& builder, DistinctNumeric<T, X, Incr, Cmp, Bool, Flags, Shift, Arith> value) |     ErrorOr<void> format(FormatBuilder& builder, DistinctNumeric<T, X, Opts...> value) | ||||||
|     { |     { | ||||||
|         return Formatter<T>::format(builder, value.value()); |         return Formatter<T>::format(builder, value.value()); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 |  | ||||||
| // TODO: When 'consteval' sufficiently-well supported by host compilers, try to
 |  | ||||||
| // provide a more usable interface like this one:
 |  | ||||||
| // https://gist.github.com/alimpfard/a3b750e8c3a2f44fb3a2d32038968ddf
 |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, Incr, Cmp, Bool, Flags, Shift, Arith, NAME) \ | #define AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, NAME, ...)                                       \ | ||||||
|     using NAME = DistinctNumeric<T, struct __##NAME##_tag, Incr, Cmp, Bool, Flags, Shift, Arith>; |     struct NAME##_decl {                                                                        \ | ||||||
| #define AK_TYPEDEF_DISTINCT_ORDERED_ID(T, NAME) AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, false, true, true, false, false, false, NAME) |         using Arithmetic [[maybe_unused]] = AK::DistinctNumericFeature::Arithmetic;             \ | ||||||
|  |         using CastToBool [[maybe_unused]] = AK::DistinctNumericFeature::CastToBool;             \ | ||||||
|  |         using Comparison [[maybe_unused]] = AK::DistinctNumericFeature::Comparison;             \ | ||||||
|  |         using Flags [[maybe_unused]] = AK::DistinctNumericFeature::Flags;                       \ | ||||||
|  |         using Increment [[maybe_unused]] = AK::DistinctNumericFeature::Increment;               \ | ||||||
|  |         using Shift [[maybe_unused]] = AK::DistinctNumericFeature::Shift;                       \ | ||||||
|  |         using NAME [[maybe_unused]] = DistinctNumeric<T, struct __##NAME##_tag, ##__VA_ARGS__>; \ | ||||||
|  |     };                                                                                          \ | ||||||
|  |     using NAME = typename NAME##_decl::NAME; | ||||||
|  | 
 | ||||||
|  | #define AK_TYPEDEF_DISTINCT_ORDERED_ID(T, NAME) AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, NAME, Comparison, CastToBool) | ||||||
| // TODO: Further type aliases?
 | // TODO: Further type aliases?
 | ||||||
| 
 | 
 | ||||||
| template<typename T, typename X, auto... Args> | template<typename T, typename X, typename... Opts> | ||||||
| struct Traits<AK::DistinctNumeric<T, X, Args...>> : public GenericTraits<AK::DistinctNumeric<T, X, Args...>> { | struct Traits<AK::DistinctNumeric<T, X, Opts...>> : public GenericTraits<AK::DistinctNumeric<T, X, Opts...>> { | ||||||
|     static constexpr bool is_trivial() { return true; } |     static constexpr bool is_trivial() { return true; } | ||||||
|     static constexpr auto hash(DistinctNumeric<T, X, Args...> const& d) { return Traits<T>::hash(d.value()); } |     static constexpr auto hash(DistinctNumeric<T, X, Opts...> const& d) { return Traits<T>::hash(d.value()); } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| using AK::DistinctNumeric; | using AK::DistinctNumeric; | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ class ForType { | ||||||
| public: | public: | ||||||
|     static void check_size() |     static void check_size() | ||||||
|     { |     { | ||||||
|         AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, false, false, false, false, false, false, TheNumeric); |         AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, TheNumeric); | ||||||
|         EXPECT_EQ(sizeof(T), sizeof(TheNumeric)); |         EXPECT_EQ(sizeof(T), sizeof(TheNumeric)); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  | @ -34,14 +34,14 @@ TEST_CASE(check_size) | ||||||
|     ForType<double>::check_size(); |     ForType<double>::check_size(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, false, false, false, false, false, BareNumeric); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, BareNumeric); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, true, false, false, false, false, false, IncrNumeric); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, IncrNumeric, Increment); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, true, false, false, false, false, CmpNumeric); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, CmpNumeric, Comparison); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, false, true, false, false, false, BoolNumeric); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, BoolNumeric, CastToBool); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, false, false, true, false, false, FlagsNumeric); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, FlagsNumeric, Flags); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, false, false, false, true, false, ShiftNumeric); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, ShiftNumeric, Shift); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, false, false, false, false, true, ArithNumeric); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, ArithNumeric, Arithmetic); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, true, true, true, true, true, true, GeneralNumeric); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, GeneralNumeric, Arithmetic, CastToBool, Comparison, Flags, Increment, Shift); | ||||||
| 
 | 
 | ||||||
| TEST_CASE(address_identity) | TEST_CASE(address_identity) | ||||||
| { | { | ||||||
|  | @ -230,21 +230,21 @@ TEST_CASE(negative_incr) | ||||||
| { | { | ||||||
|     BareNumeric a = 12; |     BareNumeric a = 12; | ||||||
|     a++; |     a++; | ||||||
|     // error: static assertion failed: 'a++' is only available for DistinctNumeric types with 'Incr'.
 |     // error: static assertion failed: 'a++' is only available for DistinctNumeric types with 'Increment'.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE(negative_cmp) | TEST_CASE(negative_cmp) | ||||||
| { | { | ||||||
|     BareNumeric a = 12; |     BareNumeric a = 12; | ||||||
|     [[maybe_unused]] auto res = (a < a); |     [[maybe_unused]] auto res = (a < a); | ||||||
|     // error: static assertion failed: 'a<b' is only available for DistinctNumeric types with 'Cmp'.
 |     // error: static assertion failed: 'a<b' is only available for DistinctNumeric types with 'Comparison'.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE(negative_bool) | TEST_CASE(negative_bool) | ||||||
| { | { | ||||||
|     BareNumeric a = 12; |     BareNumeric a = 12; | ||||||
|     [[maybe_unused]] auto res = !a; |     [[maybe_unused]] auto res = !a; | ||||||
|     // error: static assertion failed: '!a', 'a&&b', 'a||b' and similar operators are only available for DistinctNumeric types with 'Bool'.
 |     // error: static assertion failed: '!a', 'a&&b', 'a||b' and similar operators are only available for DistinctNumeric types with 'CastToBool'.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE(negative_flags) | TEST_CASE(negative_flags) | ||||||
|  | @ -265,7 +265,7 @@ TEST_CASE(negative_arith) | ||||||
| { | { | ||||||
|     BareNumeric a = 12; |     BareNumeric a = 12; | ||||||
|     [[maybe_unused]] auto res = (a + a); |     [[maybe_unused]] auto res = (a + a); | ||||||
|     // error: static assertion failed: 'a+b' is only available for DistinctNumeric types with 'Arith'.
 |     // error: static assertion failed: 'a+b' is only available for DistinctNumeric types with 'Arithmetic'.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE(negative_incompatible) | TEST_CASE(negative_incompatible) | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ | ||||||
| 
 | 
 | ||||||
| namespace JS::Bytecode { | namespace JS::Bytecode { | ||||||
| 
 | 
 | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(size_t, false, true, false, false, false, false, IdentifierTableIndex); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(size_t, IdentifierTableIndex, Comparison); | ||||||
| 
 | 
 | ||||||
| class IdentifierTable { | class IdentifierTable { | ||||||
|     AK_MAKE_NONMOVABLE(IdentifierTable); |     AK_MAKE_NONMOVABLE(IdentifierTable); | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ | ||||||
| 
 | 
 | ||||||
| namespace JS::Bytecode { | namespace JS::Bytecode { | ||||||
| 
 | 
 | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(size_t, false, true, false, false, false, false, StringTableIndex); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(size_t, StringTableIndex, Comparison); | ||||||
| 
 | 
 | ||||||
| class StringTable { | class StringTable { | ||||||
|     AK_MAKE_NONMOVABLE(StringTable); |     AK_MAKE_NONMOVABLE(StringTable); | ||||||
|  |  | ||||||
|  | @ -29,13 +29,13 @@ struct LinkError { | ||||||
|     Vector<OtherErrors> other_errors; |     Vector<OtherErrors> other_errors; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, FunctionAddress); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, FunctionAddress, Arithmetic, Comparison, Increment); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, ExternAddress); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, ExternAddress, Arithmetic, Comparison, Increment); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, TableAddress); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, TableAddress, Arithmetic, Comparison, Increment); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, GlobalAddress); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, GlobalAddress, Arithmetic, Comparison, Increment); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, ElementAddress); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, ElementAddress, Arithmetic, Comparison, Increment); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, DataAddress); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, DataAddress, Arithmetic, Comparison, Increment); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, MemoryAddress); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, MemoryAddress, Arithmetic, Comparison, Increment); | ||||||
| 
 | 
 | ||||||
| // FIXME: These should probably be made generic/virtual if/when we decide to do something more
 | // FIXME: These should probably be made generic/virtual if/when we decide to do something more
 | ||||||
| //        fancy than just a dumb interpreter.
 | //        fancy than just a dumb interpreter.
 | ||||||
|  |  | ||||||
|  | @ -57,7 +57,7 @@ AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, LocalIndex); | ||||||
| AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, GlobalIndex); | AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, GlobalIndex); | ||||||
| AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, LabelIndex); | AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, LabelIndex); | ||||||
| AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, DataIndex); | AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, DataIndex); | ||||||
| AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, true, false, true, InstructionPointer); | AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, InstructionPointer, Arithmetic, Comparison, Flags, Increment); | ||||||
| 
 | 
 | ||||||
| ParseError with_eof_check(InputStream const& stream, ParseError error_if_not_eof); | ParseError with_eof_check(InputStream const& stream, ParseError error_if_not_eof); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sam Atkins
						Sam Atkins