based

Opinionated utility library
git clone git://git.dimitrijedobrota.com/based.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

commit e0ae95c6466e73a9afcaffc16d1ab757e39525f7
parent e34ac5ad6024931bb29429f4bb5e88c2f89b3fba
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Mon, 19 May 2025 12:55:02 +0200

Rest of the operators

Diffstat:
A include/based/types/builder.hpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M include/based/types/strong.hpp | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --
M include/based/types/types.hpp | ++++++++++++++++ -----------
M test/source/types/type_test.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -------------

4 files changed, 621 insertions(+), 46 deletions(-)


diff --git a/ include/based/types/builder.hpp b/ include/based/types/builder.hpp

@@ -0,0 +1,300 @@

#pragma once

// NOLINTBEGIN(*macro-usage*,*macro-parentheses*,*naming*)

namespace based
{

template<typename V>
class builder_type
{
protected:
V m_val; // NOLINT (*protected*)

public:
template<class FV1>
using rebind = builder_type<V>;

using value_type = builder_type;
using basic_type = V;

constexpr ~builder_type() = default;

constexpr explicit builder_type()
: m_val(V())
{
}

constexpr explicit builder_type(V value)
: m_val(value)
{
}

constexpr builder_type(const builder_type&) = default;
constexpr builder_type& operator=(const builder_type&) = default;

constexpr builder_type(builder_type&&) = default;
constexpr builder_type& operator=(builder_type&&) = default;

[[nodiscard]] auto value() const { return m_val; }
};

#define BASED_B_DETAIL_COMMON(Name) \
template<class FV1> \
using rebind = Name<V, FV1>; \
\
using base_type::base_type; \
using base_type::operator=; \
\
using value_type = typename base_type::value_type; \
using basic_type = typename value_type::basic_type; \
\
/* NOLINTNEXTLINE(*crtp*) */ \
constexpr explicit Name(value_type value) \
: base_type(value) \
{ \
}

#define BASED_B_DETAIL_TEMPLATE(Name) \
template<class V, class FV = void> \
class Name : public V::template rebind<FV> \
{ \
using base_type = typename V::template rebind<FV>; \
\
public: \
BASED_B_DETAIL_COMMON(Name) X(FV, Name) \
};

#define BASED_B_DETAIL_SPECIALIZATION(Name) \
template<class V> \
class Name<V, void> : public V::template rebind<Name<V>> \
{ \
using base_type = typename V::template rebind<Name<V>>; \
\
public: \
BASED_B_DETAIL_COMMON(Name) X(Name, Name) \
};

#define BASED_BUILDER_DECORATOR(Name) \
BASED_B_DETAIL_TEMPLATE(Name) BASED_B_DETAIL_SPECIALIZATION(Name)

#define X(FV, Name) \
/* NOLINTNEXTLINE(*explicit*) */ \
Name(basic_type rhs) \
: base_type(rhs) \
{ \
} \
\
Name& operator=(V rhs) \
{ \
this->m_val = rhs; \
return *this; \
}

BASED_BUILDER_DECORATOR(ImplicitFrom)
#undef X

#define X(FV, Name) \
operator basic_type() \
{ \
return this->m_val; \
} \
\
operator const basic_type() const \
{ \
return this->m_val; \
}
BASED_BUILDER_DECORATOR(ImplicitTo)
#undef X

#define X(FV, Name) \
friend constexpr bool operator==(FV lhs, FV rhs) \
{ \
return lhs.m_val == rhs.m_val; \
}
BASED_BUILDER_DECORATOR(Comparable)
#undef X

#define X(FV, Name) \
friend constexpr auto operator<=>(FV lhs, FV rhs) \
{ \
return lhs.m_val <=> rhs.m_val; \
}
BASED_BUILDER_DECORATOR(Ordered)
#undef X

#define X(FV, Name) \
constexpr auto& operator+=(FV rhs) \
{ \
this->m_val += rhs.m_val; \
return *this; \
} \
friend constexpr auto operator+(FV lhs, FV rhs) \
{ \
return FV(lhs.m_val + rhs.m_val); \
}
BASED_BUILDER_DECORATOR(Addable)
#undef X

#define X(FV, Name) \
constexpr auto& operator-=(FV rhs) \
{ \
this->m_val -= rhs.m_val; \
return *this; \
} \
friend constexpr auto operator-(FV lhs, FV rhs) \
{ \
return FV(lhs.m_val - rhs.m_val); \
}
BASED_BUILDER_DECORATOR(Subtractable)
#undef X

#define X(FV, Name) \
constexpr auto& operator*=(FV rhs) \
{ \
this->m_val *= rhs.m_val; \
return *this; \
} \
friend constexpr auto operator*(FV lhs, FV rhs) \
{ \
return FV(lhs.m_val * rhs.m_val); \
}
BASED_BUILDER_DECORATOR(Multipliable)
#undef X

#define X(FV, Name) \
constexpr auto& operator/=(FV rhs) \
{ \
this->m_val /= rhs.m_val; \
return *this; \
} \
friend constexpr auto operator/(FV lhs, FV rhs) \
{ \
return FV(lhs.m_val / rhs.m_val); \
}
BASED_BUILDER_DECORATOR(Divisible)
#undef X

#define X(FV, Name) \
constexpr auto& operator%=(FV rhs) \
{ \
this->m_val %= rhs.m_val; \
return *this; \
} \
friend constexpr auto operator%(FV lhs, FV rhs) \
{ \
return FV(lhs.m_val % rhs.m_val); \
}
BASED_BUILDER_DECORATOR(Modable)
#undef X

#define X(FV, Name) \
friend constexpr auto& operator++(FV& lhs) \
{ \
++lhs.value; \
return lhs; \
}
BASED_BUILDER_DECORATOR(PreIncrementable)
#undef X

#define X(FV, Name) \
friend constexpr auto operator++(FV lhs, int) \
{ \
return FV(lhs.m_val++); \
}
BASED_BUILDER_DECORATOR(PostIncrementable)
#undef X

#define X(FV, Name) \
friend constexpr auto& operator--(FV& lhs) \
{ \
--lhs.value; \
return lhs; \
}
BASED_BUILDER_DECORATOR(PreDecrementable)
#undef X

#define X(FV, Name) \
friend constexpr auto operator--(FV lhs, int) \
{ \
return FV(lhs.m_val--); \
}
BASED_BUILDER_DECORATOR(PostDecrementable)
#undef X

#define X(FV, Name) \
friend constexpr auto operator~(FV rhs) \
{ \
return FV(~rhs.m_val); \
}
BASED_BUILDER_DECORATOR(Notable)
#undef X

#define X(FV, Name) \
constexpr auto& operator&=(FV rhs) \
{ \
this->m_val &= rhs.m_val; \
return *this; \
} \
friend constexpr auto operator&(FV lhs, FV rhs) \
{ \
return FV(lhs.m_val & rhs.m_val); \
}
BASED_BUILDER_DECORATOR(Andable)
#undef X

#define X(FV, Name) \
constexpr auto& operator|=(FV rhs) \
{ \
this->m_val |= rhs.m_val; \
return *this; \
} \
friend constexpr auto operator|(FV lhs, FV rhs) \
{ \
return FV(lhs.m_val | rhs.m_val); \
}
BASED_BUILDER_DECORATOR(Orable)
#undef X

#define X(FV, Name) \
constexpr auto& operator^=(FV rhs) \
{ \
this->m_val ^= rhs.m_val; \
return *this; \
} \
friend constexpr auto operator^(FV lhs, FV rhs) \
{ \
return FV(lhs.m_val ^ rhs.m_val); \
}
BASED_BUILDER_DECORATOR(Xorable)
#undef X

#define X(FV, Name) \
constexpr auto& operator<<=(FV rhs) \
{ \
this->m_val <<= rhs.m_val; \
return *this; \
} \
friend constexpr auto operator<<(FV lhs, FV rhs) \
{ \
return FV(lhs.m_val << rhs.m_val); \
}
BASED_BUILDER_DECORATOR(LShiftable)
#undef X

#define X(FV, Name) \
constexpr auto& operator>>=(FV rhs) \
{ \
this->m_val >>= rhs.m_val; \
return *this; \
} \
friend constexpr auto operator>>(FV lhs, FV rhs) \
{ \
return FV(lhs.m_val >> rhs.m_val); \
}
BASED_BUILDER_DECORATOR(RShiftable)
#undef X

} // namespace based

// NOLINTEND(*macro-usage*,*macro-parentheses*,*naming*)

diff --git a/ include/based/types/strong.hpp b/ include/based/types/strong.hpp

@@ -79,8 +79,7 @@ template<class LHS, class RHS>

})
constexpr auto& operator+=(LHS& lhs, RHS& rhs)
{
lhs.value += rhs.value;
return lhs;
return lhs = lhs + rhs;
}

template<class LHS, class RHS>

@@ -94,6 +93,16 @@ constexpr auto operator-(LHS lhs, RHS rhs)

}

template<class LHS, class RHS>
requires(requires(LHS lhs, RHS rhs) {
requires subtractable<LHS, RHS>;
requires SameAs<LHS, decltype(sub(lhs, rhs))>;
})
constexpr auto& operator-=(LHS& lhs, RHS& rhs)
{
return lhs = lhs - rhs;
}

template<class LHS, class RHS>
concept multiplyable = requires(LHS lhs, RHS rhs) { mul(lhs, rhs); };

template<class LHS, class RHS>

@@ -104,6 +113,16 @@ constexpr auto operator*(LHS lhs, RHS rhs)

}

template<class LHS, class RHS>
requires(requires(LHS lhs, RHS rhs) {
requires multiplyable<LHS, RHS>;
requires SameAs<LHS, decltype(mul(lhs, rhs))>;
})
constexpr auto& operator*=(LHS& lhs, RHS& rhs)
{
return lhs = lhs * rhs;
}

template<class LHS, class RHS>
concept divisible = requires(LHS lhs, RHS rhs) { div(lhs, rhs); };

template<class LHS, class RHS>

@@ -114,6 +133,16 @@ constexpr auto operator/(LHS lhs, RHS rhs)

}

template<class LHS, class RHS>
requires(requires(LHS lhs, RHS rhs) {
requires divisible<LHS, RHS>;
requires SameAs<LHS, decltype(div(lhs, rhs))>;
})
constexpr auto& operator/=(LHS& lhs, RHS& rhs)
{
return lhs = lhs / rhs;
}

template<class LHS, class RHS>
concept modable = requires(LHS lhs, RHS rhs) { mod(lhs, rhs); };

template<class LHS, class RHS>

@@ -124,6 +153,56 @@ constexpr auto operator%(LHS lhs, RHS rhs)

}

template<class LHS, class RHS>
requires(requires(LHS lhs, RHS rhs) {
requires modable<LHS, RHS>;
requires SameAs<LHS, decltype(mod(lhs, rhs))>;
})
constexpr auto& operator%=(LHS& lhs, RHS& rhs)
{
return lhs = lhs % rhs;
}

template<class LHS, class RHS>
concept lshiftable = requires(LHS lhs, RHS rhs) { lshift(lhs, rhs); };

template<class LHS, class RHS>
requires lshiftable<LHS, RHS>
constexpr auto operator<<(LHS lhs, RHS rhs)
{
return BASED_DETAIL_MACRO(lshift(lhs, rhs), lhs.value << rhs.value);
}

template<class LHS, class RHS>
requires(requires(LHS lhs, RHS rhs) {
requires lshiftable<LHS, RHS>;
requires SameAs<LHS, decltype(lshift(lhs, rhs))>;
})
constexpr auto& operator<<=(LHS& lhs, RHS& rhs)
{
return lhs = lhs << rhs;
}

template<class LHS, class RHS>
concept rshiftable = requires(LHS lhs, RHS rhs) { rshift(lhs, rhs); };

template<class LHS, class RHS>
requires rshiftable<LHS, RHS>
constexpr auto operator>>(LHS lhs, RHS rhs)
{
return BASED_DETAIL_MACRO(rshift(lhs, rhs), lhs.value >> rhs.value);
}

template<class LHS, class RHS>
requires(requires(LHS lhs, RHS rhs) {
requires rshiftable<LHS, RHS>;
requires SameAs<LHS, decltype(rshift(lhs, rhs))>;
})
constexpr auto& operator>>=(LHS& lhs, RHS& rhs)
{
return lhs = lhs >> rhs;
}

template<class LHS, class RHS>
concept andable = requires(LHS lhs, RHS rhs) { land(lhs, rhs); };

template<class LHS, class RHS>

@@ -134,6 +213,16 @@ constexpr auto operator&(LHS lhs, RHS rhs)

}

template<class LHS, class RHS>
requires(requires(LHS lhs, RHS rhs) {
requires andable<LHS, RHS>;
requires SameAs<LHS, decltype(land(lhs, rhs))>;
})
constexpr auto& operator&=(LHS& lhs, RHS& rhs)
{
return lhs = lhs & rhs;
}

template<class LHS, class RHS>
concept orable = requires(LHS lhs, RHS rhs) { lor(lhs, rhs); };

template<class LHS, class RHS>

@@ -144,6 +233,16 @@ constexpr auto operator|(LHS lhs, RHS rhs)

}

template<class LHS, class RHS>
requires(requires(LHS lhs, RHS rhs) {
requires orable<LHS, RHS>;
requires SameAs<LHS, decltype(lor(lhs, rhs))>;
})
constexpr auto& operator|=(LHS& lhs, RHS& rhs)
{
return lhs = lhs | rhs;
}

template<class LHS, class RHS>
concept xorable = requires(LHS lhs, RHS rhs) { lxor(lhs, rhs); };

template<class LHS, class RHS>

@@ -153,6 +252,27 @@ constexpr auto operator^(LHS lhs, RHS rhs)

return BASED_DETAIL_MACRO(lxor(lhs, rhs), lhs.value ^ rhs.value);
}

template<class LHS, class RHS>
requires(requires(LHS lhs, RHS rhs) {
requires xorable<LHS, RHS>;
requires SameAs<LHS, decltype(lxor(lhs, rhs))>;
})
constexpr auto& operator^=(LHS& lhs, RHS& rhs)
{
return lhs = lhs ^ rhs;
}

template<class LHS>
concept lnotable = requires(LHS lhs) { lnot(lhs); };

template<class LHS>
requires lnotable<LHS>
constexpr auto operator~(LHS lhs)
{
lhs.value = ~lhs.value;
return lhs;
}

template<class LHS>
concept preincable = requires(LHS lhs) { preinc(lhs); };

diff --git a/ include/based/types/types.hpp b/ include/based/types/types.hpp

@@ -1,5 +1,4 @@

#pragma once

#include "based/macro/foreach_1.hpp"
#include "based/types/strong.hpp"

@@ -20,7 +19,7 @@ using bu64 = unsigned long int;


using size_t = bu64;

#define TYPE(Name) \
#define BASED_DETAIL_TYPE(Name) \
/* NOLINTNEXTLINE(*macro*) */ \
struct Name : strong_type<b##Name, Name> \
{ \

@@ -37,10 +36,15 @@ using size_t = bu64;

} \
} // namespace literals

TYPE(i8)
TYPE(i16)
TYPE(i32)
TYPE(i64)
BASED_DETAIL_TYPE(i8)
BASED_DETAIL_TYPE(i16)
BASED_DETAIL_TYPE(i32)
BASED_DETAIL_TYPE(i64)

BASED_DETAIL_TYPE(u8)
BASED_DETAIL_TYPE(u16)
BASED_DETAIL_TYPE(u32)
BASED_DETAIL_TYPE(u64)

#define BASED_DETAIL_OP_UNARY(Prefix, Name, Index) \
auto Name(Prefix##8)->Prefix##8; \

@@ -74,11 +78,6 @@ BASED_FOREACH_1(

i, BASED_DETAIL_OP_BINARY, compare, order, add, sub, mul, div, mod
)

TYPE(u8)
TYPE(u16)
TYPE(u32)
TYPE(u64)

BASED_FOREACH_1(u, BASED_DETAIL_OP_UNARY, preinc, postinc, predec, postdec)
BASED_FOREACH_1(
u,

@@ -90,11 +89,17 @@ BASED_FOREACH_1(

mul,
div,
mod,
lshift,
rshift,
land,
lor,
lxor
)

#undef BASED_DETAIL_TYPE
#undef BASED_DETAIL_OP_UNARY
#undef BASED_DETAIL_OP_BINARY

// NOLINTEND(google-runtime-int)

} // namespace based

diff --git a/ test/source/types/type_test.cpp b/ test/source/types/type_test.cpp

@@ -1,4 +1,4 @@

#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
// #define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE

#include <catch2/catch_test_macros.hpp>

@@ -16,7 +16,6 @@ TEST_CASE("u8", "[types/u8]")

// clang-format off
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs - rhs } -> SameAs<u8>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs + rhs } -> SameAs<u8>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs - rhs } -> SameAs<u8>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs * rhs } -> SameAs<u8>; });

@@ -25,14 +24,27 @@ TEST_CASE("u8", "[types/u8]")

STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs & rhs } -> SameAs<u8>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs | rhs } -> SameAs<u8>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs ^ rhs } -> SameAs<u8>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs << rhs } -> SameAs<u8>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs >> rhs } -> SameAs<u8>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs += rhs } -> SameAs<u8&>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs -= rhs } -> SameAs<u8&>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs *= rhs } -> SameAs<u8&>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs /= rhs } -> SameAs<u8&>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs %= rhs } -> SameAs<u8&>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs &= rhs } -> SameAs<u8&>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs |= rhs } -> SameAs<u8&>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs ^= rhs } -> SameAs<u8&>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs <<= rhs } -> SameAs<u8&>; });
STATIC_REQUIRE(requires(u8 lhs, u8 rhs) { { lhs >>= rhs } -> SameAs<u8&>; });

STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs - rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs + rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs - rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs * rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs / rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs << rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs >> rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs % rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs & rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u8 lhs, u16 rhs) { { lhs | rhs } -> SameAs<u16>; });

@@ -40,24 +52,26 @@ TEST_CASE("u8", "[types/u8]")


STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs - rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs + rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs - rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs * rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs / rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs % rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs << rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs >> rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs & rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs | rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs ^ rhs } -> SameAs<u32>; });

STATIC_REQUIRE(requires(u8 lhs, u32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs + rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs * rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs / rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs % rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs << rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs >> rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs & rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs | rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u8 lhs, u64 rhs) { { lhs ^ rhs } -> SameAs<u64>; });

@@ -69,48 +83,72 @@ TEST_CASE("u16", "[types/u16]")

// clang-format off
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs - rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs + rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs - rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs * rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs / rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs % rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs << rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs >> rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs & rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs | rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs ^ rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs += rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs -= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs *= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs /= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs %= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs &= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs |= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs ^= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs <<= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u8 rhs) { { lhs >>= rhs } -> SameAs<u16&>; });

STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs - rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs + rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs - rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs * rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs / rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs % rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs << rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs >> rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs & rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs | rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs ^ rhs } -> SameAs<u16>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs += rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs -= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs *= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs /= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs %= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs &= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs |= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs ^= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs <<= rhs } -> SameAs<u16&>; });
STATIC_REQUIRE(requires(u16 lhs, u16 rhs) { { lhs >>= rhs } -> SameAs<u16&>; });

STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs - rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs + rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs - rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs * rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs / rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs % rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs << rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs >> rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs & rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs | rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs ^ rhs } -> SameAs<u32>; });

STATIC_REQUIRE(requires(u16 lhs, u32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs + rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs * rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs / rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs % rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs << rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs >> rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs & rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs | rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u16 lhs, u64 rhs) { { lhs ^ rhs } -> SameAs<u64>; });

@@ -122,48 +160,82 @@ TEST_CASE("u32", "[types/u32]")

// clang-format off
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs - rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs + rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs - rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs * rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs / rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs % rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs << rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs >> rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs & rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs | rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs ^ rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs += rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs -= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs *= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs /= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs %= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs &= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs |= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs ^= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs <<= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u8 rhs) { { lhs >>= rhs } -> SameAs<u32&>; });

STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs - rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs + rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs - rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs * rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs / rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs % rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs << rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs >> rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs & rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs | rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs ^ rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs += rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs -= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs *= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs /= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs %= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs &= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs |= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs ^= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs <<= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u16 rhs) { { lhs >>= rhs } -> SameAs<u32&>; });

STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs - rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs + rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs - rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs * rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs / rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs % rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs << rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs >> rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs & rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs | rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs ^ rhs } -> SameAs<u32>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs += rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs -= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs *= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs /= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs %= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs &= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs |= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs ^= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs <<= rhs } -> SameAs<u32&>; });
STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs >>= rhs } -> SameAs<u32&>; });

STATIC_REQUIRE(requires(u32 lhs, u32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs + rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs * rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs / rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs % rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs << rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs >> rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs & rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs | rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u32 lhs, u64 rhs) { { lhs ^ rhs } -> SameAs<u64>; });

@@ -175,51 +247,95 @@ TEST_CASE("u64", "[types/u64]")

// clang-format off
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs + rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs * rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs / rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs % rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs << rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs >> rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs & rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs | rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs ^ rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs += rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs -= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs *= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs /= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs %= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs &= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs |= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs ^= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs <<= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u8 rhs) { { lhs >>= rhs } -> SameAs<u64&>; });

STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs + rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs * rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs / rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs % rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs << rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs >> rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs & rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs | rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs ^ rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs += rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs -= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs *= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs /= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs %= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs &= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs |= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs ^= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs <<= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u16 rhs) { { lhs >>= rhs } -> SameAs<u64&>; });

STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs + rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs * rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs / rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs % rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs << rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs >> rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs & rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs | rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs ^ rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs += rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs -= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs *= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs /= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs %= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs &= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs |= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs ^= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs <<= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs >>= rhs } -> SameAs<u64&>; });

STATIC_REQUIRE(requires(u64 lhs, u32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs + rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs - rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs * rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs / rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs % rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs << rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs >> rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs & rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs | rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs ^ rhs } -> SameAs<u64>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs += rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs -= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs *= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs /= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs %= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs &= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs |= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs ^= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs <<= rhs } -> SameAs<u64&>; });
STATIC_REQUIRE(requires(u64 lhs, u64 rhs) { { lhs >>= rhs } -> SameAs<u64&>; });
// clang-format on
}

@@ -233,16 +349,19 @@ TEST_CASE("i8", "[types/i8]")

// clang-format off
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs - rhs } -> SameAs<i8>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs + rhs } -> SameAs<i8>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs - rhs } -> SameAs<i8>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs * rhs } -> SameAs<i8>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs / rhs } -> SameAs<i8>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs % rhs } -> SameAs<i8>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs += rhs } -> SameAs<i8&>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs -= rhs } -> SameAs<i8&>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs *= rhs } -> SameAs<i8&>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs /= rhs } -> SameAs<i8&>; });
STATIC_REQUIRE(requires(i8 lhs, i8 rhs) { { lhs %= rhs } -> SameAs<i8&>; });

STATIC_REQUIRE(requires(i8 lhs, i16 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i8 lhs, i16 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i8 lhs, i16 rhs) { { lhs - rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i8 lhs, i16 rhs) { { lhs + rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i8 lhs, i16 rhs) { { lhs - rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i8 lhs, i16 rhs) { { lhs * rhs } -> SameAs<i16>; });

@@ -251,7 +370,6 @@ TEST_CASE("i8", "[types/i8]")


STATIC_REQUIRE(requires(i8 lhs, i32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i8 lhs, i32 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i8 lhs, i32 rhs) { { lhs - rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i8 lhs, i32 rhs) { { lhs + rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i8 lhs, i32 rhs) { { lhs - rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i8 lhs, i32 rhs) { { lhs * rhs } -> SameAs<i32>; });

@@ -260,7 +378,6 @@ TEST_CASE("i8", "[types/i8]")


STATIC_REQUIRE(requires(i8 lhs, i32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i8 lhs, i64 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i8 lhs, i64 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i8 lhs, i64 rhs) { { lhs + rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i8 lhs, i64 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i8 lhs, i64 rhs) { { lhs * rhs } -> SameAs<i64>; });

@@ -274,25 +391,32 @@ TEST_CASE("i16", "[types/i16]")

// clang-format off
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs - rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs + rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs - rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs * rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs / rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs % rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs += rhs } -> SameAs<i16&>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs -= rhs } -> SameAs<i16&>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs *= rhs } -> SameAs<i16&>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs /= rhs } -> SameAs<i16&>; });
STATIC_REQUIRE(requires(i16 lhs, i8 rhs) { { lhs %= rhs } -> SameAs<i16&>; });

STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs - rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs + rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs - rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs * rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs / rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs % rhs } -> SameAs<i16>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs += rhs } -> SameAs<i16&>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs -= rhs } -> SameAs<i16&>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs *= rhs } -> SameAs<i16&>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs /= rhs } -> SameAs<i16&>; });
STATIC_REQUIRE(requires(i16 lhs, i16 rhs) { { lhs %= rhs } -> SameAs<i16&>; });

STATIC_REQUIRE(requires(i16 lhs, i32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i16 lhs, i32 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i16 lhs, i32 rhs) { { lhs - rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i16 lhs, i32 rhs) { { lhs + rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i16 lhs, i32 rhs) { { lhs - rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i16 lhs, i32 rhs) { { lhs * rhs } -> SameAs<i32>; });

@@ -301,7 +425,6 @@ TEST_CASE("i16", "[types/i16]")


STATIC_REQUIRE(requires(i16 lhs, i32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i16 lhs, i64 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i16 lhs, i64 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i16 lhs, i64 rhs) { { lhs + rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i16 lhs, i64 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i16 lhs, i64 rhs) { { lhs * rhs } -> SameAs<i64>; });

@@ -315,34 +438,45 @@ TEST_CASE("i32", "[types/i32]")

// clang-format off
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs - rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs + rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs - rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs * rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs / rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs % rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs += rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs -= rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs *= rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs /= rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i8 rhs) { { lhs %= rhs } -> SameAs<i32&>; });

STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs - rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs + rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs - rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs * rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs / rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs % rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs += rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs -= rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs *= rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs /= rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i16 rhs) { { lhs %= rhs } -> SameAs<i32&>; });

STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs - rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs + rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs - rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs * rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs / rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs % rhs } -> SameAs<i32>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs += rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs -= rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs *= rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs /= rhs } -> SameAs<i32&>; });
STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs %= rhs } -> SameAs<i32&>; });

STATIC_REQUIRE(requires(i32 lhs, i32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i32 lhs, i64 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i32 lhs, i64 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i32 lhs, i64 rhs) { { lhs + rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i32 lhs, i64 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i32 lhs, i64 rhs) { { lhs * rhs } -> SameAs<i64>; });

@@ -356,38 +490,54 @@ TEST_CASE("i64", "[types/i64]")

// clang-format off
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs + rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs * rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs / rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs % rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs += rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs -= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs *= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs /= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i8 rhs) { { lhs %= rhs } -> SameAs<i64&>; });

STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs + rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs * rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs / rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs % rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs += rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs -= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs *= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs /= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i16 rhs) { { lhs %= rhs } -> SameAs<i64&>; });

STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs + rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs * rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs / rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs % rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs += rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs -= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs *= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs /= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs %= rhs } -> SameAs<i64&>; });

STATIC_REQUIRE(requires(i64 lhs, i32 rhs) { { lhs == rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs <= rhs } -> SameAs<bool>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs + rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs - rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs * rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs / rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs % rhs } -> SameAs<i64>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs += rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs -= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs *= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs /= rhs } -> SameAs<i64&>; });
STATIC_REQUIRE(requires(i64 lhs, i64 rhs) { { lhs %= rhs } -> SameAs<i64&>; });
// clang-format on
}