From 25d9d24f94746450caa9abb4558c34ef589ef1b2 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 18 Dec 2023 23:08:24 +0000 Subject: [PATCH] Strong typedef: Add mixin for scalable integer --- src/core/strong_typedef_type.hpp | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/core/strong_typedef_type.hpp b/src/core/strong_typedef_type.hpp index a98caf611d..bb9df55a0e 100644 --- a/src/core/strong_typedef_type.hpp +++ b/src/core/strong_typedef_type.hpp @@ -106,6 +106,67 @@ namespace StrongType { }; }; + /** + * Mix-in which makes the new Typedef behave more like an integer. This means you can add and subtract from it. + * + * Operators like divide, multiply and module are permitted. + */ + struct IntegerScalable { + template + struct mixin { + friend constexpr TType &operator ++(TType &lhs) { lhs.value++; return lhs; } + friend constexpr TType &operator --(TType &lhs) { lhs.value--; return lhs; } + friend constexpr TType operator ++(TType &lhs, int) { TType res = lhs; lhs.value++; return res; } + friend constexpr TType operator --(TType &lhs, int) { TType res = lhs; lhs.value--; return res; } + + friend constexpr TType &operator +=(TType &lhs, const TType &rhs) { lhs.value += rhs.value; return lhs; } + friend constexpr TType operator +(const TType &lhs, const TType &rhs) { return TType{ lhs.value + rhs.value }; } + friend constexpr TType operator +(const TType &lhs, const TBaseType &rhs) { return TType{ lhs.value + rhs }; } + + friend constexpr TType &operator -=(TType &lhs, const TType &rhs) { lhs.value -= rhs.value; return lhs; } + friend constexpr TType operator -(const TType &lhs, const TType &rhs) { return TType{ lhs.value - rhs.value }; } + friend constexpr TType operator -(const TType &lhs, const TBaseType &rhs) { return TType{ lhs.value - rhs }; } + + friend constexpr TType &operator *=(TType &lhs, const TType &rhs) { lhs.value *= rhs.value; return lhs; } + friend constexpr TType operator *(const TType &lhs, const TType &rhs) { return TType{ lhs.value * rhs.value }; } + friend constexpr TType operator *(const TType &lhs, const TBaseType &rhs) { return TType{ lhs.value * rhs }; } + + friend constexpr TType &operator /=(TType &lhs, const TType &rhs) { lhs.value /= rhs.value; return lhs; } + friend constexpr TType operator /(const TType &lhs, const TType &rhs) { return TType{ lhs.value / rhs.value }; } + friend constexpr TType operator /(const TType &lhs, const TBaseType &rhs) { return TType{ lhs.value / rhs }; } + + friend constexpr TType &operator %=(TType &lhs, const TType &rhs) { lhs.value %= rhs.value; return lhs; } + friend constexpr TType operator %(const TType &lhs, const TType &rhs) { return TType{ lhs.value % rhs.value }; } + friend constexpr TType operator %(const TType &lhs, const TBaseType &rhs) { return TType{ lhs.value % rhs }; } + + friend constexpr TType operator -(const TType &lhs) { return TType{ -lhs.value }; } + + /* For most new types, the rest of the operators make no sense. */ + + constexpr TType &operator &=(const TType &rhs) = delete; + constexpr TType operator &(const TType &rhs) = delete; + constexpr TType operator &(const TBaseType &rhs) = delete; + + constexpr TType &operator |=(const TType &rhs) = delete; + constexpr TType operator |(const TType &rhs) = delete; + constexpr TType operator |(const TBaseType &rhs) = delete; + + constexpr TType &operator ^=(const TType &rhs) = delete; + constexpr TType operator ^(const TType &rhs) = delete; + constexpr TType operator ^(const TBaseType &rhs) = delete; + + constexpr TType &operator <<=(const TType &rhs) = delete; + constexpr TType operator <<(const TType &rhs) = delete; + constexpr TType operator <<(const TBaseType &rhs) = delete; + + constexpr TType &operator >>=(const TType &rhs) = delete; + constexpr TType operator >>(const TType &rhs) = delete; + constexpr TType operator >>(const TBaseType &rhs) = delete; + + constexpr TType operator ~() = delete; + }; + }; + /** * Mix-in which makes the new Typedef compatible with another type (which is not the base type). * @@ -164,6 +225,7 @@ namespace StrongType { /* Only allow TProperties classes access to the internal value. Everyone else needs to call .base(). */ friend struct Compare; friend struct Integer; + friend struct IntegerScalable; template friend struct Compatible; /* GCC / MSVC don't pick up on the "friend struct" above, where CLang does.