From e85df4abc54fb924d7cab2d9fa03e64f01232f1f Mon Sep 17 00:00:00 2001 From: Qudix <17361645+Qudix@users.noreply.github.com> Date: Tue, 28 May 2024 09:41:46 -0500 Subject: [PATCH] feat: start moving things from `PCH.h` --- CommonLibF4/cmake/sourcelist.cmake | 1 + CommonLibF4/include/F4SE/Impl/PCH.h | 226 ++-------------------------- CommonLibF4/include/REX/REX.h | 169 +++++++++++++++++++++ 3 files changed, 183 insertions(+), 213 deletions(-) create mode 100644 CommonLibF4/include/REX/REX.h diff --git a/CommonLibF4/cmake/sourcelist.cmake b/CommonLibF4/cmake/sourcelist.cmake index 90d1f0da..f35053a5 100644 --- a/CommonLibF4/cmake/sourcelist.cmake +++ b/CommonLibF4/cmake/sourcelist.cmake @@ -367,6 +367,7 @@ set(SOURCES include/REL/Version.h include/REX/PS4.h include/REX/PS4/SCEPAD.h + include/REX/REX.h include/REX/W32.h include/REX/W32/ADVAPI32.h include/REX/W32/BASE.h diff --git a/CommonLibF4/include/F4SE/Impl/PCH.h b/CommonLibF4/include/F4SE/Impl/PCH.h index 2a5e7441..8bb56cf6 100644 --- a/CommonLibF4/include/F4SE/Impl/PCH.h +++ b/CommonLibF4/include/F4SE/Impl/PCH.h @@ -46,6 +46,7 @@ static_assert( #include #pragma warning(pop) +#include "REX/REX.h" #include "REX/W32/KERNEL32.h" #include "REX/W32/USER32.h" @@ -262,103 +263,22 @@ namespace F4SE std::size_t _left{ 0 }; }; + + // backwards compat template < - class Enum, - class Underlying = std::underlying_type_t> - class enumeration + class E, + class U = std::underlying_type_t> + class enumeration : public REX::EnumSet { - public: - using enum_type = Enum; - using underlying_type = Underlying; - - static_assert(std::is_enum_v, "enum_type must be an enum"); - static_assert(std::is_integral_v, "underlying_type must be an integral"); - - constexpr enumeration() noexcept = default; - - constexpr enumeration(const enumeration&) noexcept = default; - - constexpr enumeration(enumeration&&) noexcept = default; - - template // NOLINTNEXTLINE(google-explicit-constructor) - constexpr enumeration(enumeration a_rhs) noexcept : - _impl(static_cast(a_rhs.get())) - {} + using super = REX::EnumSet; - template - constexpr enumeration(Args... a_values) noexcept // - requires(std::same_as&&...) : - _impl((static_cast(a_values) | ...)) - {} - - ~enumeration() noexcept = default; - - constexpr enumeration& operator=(const enumeration&) noexcept = default; - constexpr enumeration& operator=(enumeration&&) noexcept = default; - - template - constexpr enumeration& operator=(enumeration a_rhs) noexcept - { - _impl = static_cast(a_rhs.get()); - } - - constexpr enumeration& operator=(enum_type a_value) noexcept - { - _impl = static_cast(a_value); - return *this; - } - - [[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast(0); } - - [[nodiscard]] constexpr enum_type operator*() const noexcept { return get(); } - [[nodiscard]] constexpr enum_type get() const noexcept { return static_cast(_impl); } - [[nodiscard]] constexpr underlying_type underlying() const noexcept { return _impl; } - - template - constexpr enumeration& set(Args... a_args) noexcept // - requires(std::same_as&&...) - { - _impl |= (static_cast(a_args) | ...); - return *this; - } - - template - constexpr enumeration& reset(Args... a_args) noexcept // - requires(std::same_as&&...) - { - _impl &= ~(static_cast(a_args) | ...); - return *this; - } - - constexpr enumeration& reset() noexcept - { - _impl = 0; - return *this; - } - - template - [[nodiscard]] constexpr bool any(Args... a_args) const noexcept // - requires(std::same_as&&...) - { - return (_impl & (static_cast(a_args) | ...)) != static_cast(0); - } - - template - [[nodiscard]] constexpr bool all(Args... a_args) const noexcept // - requires(std::same_as&&...) - { - return (_impl & (static_cast(a_args) | ...)) == (static_cast(a_args) | ...); - } - - template - [[nodiscard]] constexpr bool none(Args... a_args) const noexcept // - requires(std::same_as&&...) - { - return (_impl & (static_cast(a_args) | ...)) == static_cast(0); - } + public: + using enum_type = E; + using underlying_type = U; - private: - underlying_type _impl{ 0 }; + using super::super; + using super::operator=; + using super::operator*; }; template @@ -369,125 +289,10 @@ namespace F4SE } } -#define F4SE_MAKE_LOGICAL_OP(a_op, a_result) \ - template \ - [[nodiscard]] constexpr a_result operator a_op(enumeration a_lhs, enumeration a_rhs) noexcept \ - { \ - return a_lhs.get() a_op a_rhs.get(); \ - } \ - \ - template \ - [[nodiscard]] constexpr a_result operator a_op(enumeration a_lhs, E a_rhs) noexcept \ - { \ - return a_lhs.get() a_op a_rhs; \ - } - -#define F4SE_MAKE_ARITHMETIC_OP(a_op) \ - template \ - [[nodiscard]] constexpr auto operator a_op(enumeration a_enum, U a_shift) noexcept \ - ->enumeration \ - { \ - return static_cast(static_cast(a_enum.get()) a_op a_shift); \ - } \ - \ - template \ - constexpr auto operator a_op##=(enumeration& a_enum, U a_shift) noexcept \ - ->enumeration& \ - { \ - return a_enum = a_enum a_op a_shift; \ - } - -#define F4SE_MAKE_ENUMERATION_OP(a_op) \ - template \ - [[nodiscard]] constexpr auto operator a_op(enumeration a_lhs, enumeration a_rhs) noexcept \ - ->enumeration> \ - { \ - return static_cast(static_cast(a_lhs.get()) a_op static_cast(a_rhs.get())); \ - } \ - \ - template \ - [[nodiscard]] constexpr auto operator a_op(enumeration a_lhs, E a_rhs) noexcept \ - ->enumeration \ - { \ - return static_cast(static_cast(a_lhs.get()) a_op static_cast(a_rhs)); \ - } \ - \ - template \ - [[nodiscard]] constexpr auto operator a_op(E a_lhs, enumeration a_rhs) noexcept \ - ->enumeration \ - { \ - return static_cast(static_cast(a_lhs) a_op static_cast(a_rhs.get())); \ - } \ - \ - template \ - constexpr auto operator a_op##=(enumeration& a_lhs, enumeration a_rhs) noexcept \ - ->enumeration& \ - { \ - return a_lhs = a_lhs a_op a_rhs; \ - } \ - \ - template \ - constexpr auto operator a_op##=(enumeration& a_lhs, E a_rhs) noexcept \ - ->enumeration& \ - { \ - return a_lhs = a_lhs a_op a_rhs; \ - } \ - \ - template \ - constexpr auto operator a_op##=(E& a_lhs, enumeration a_rhs) noexcept \ - ->E& \ - { \ - return a_lhs = *(a_lhs a_op a_rhs); \ - } - -#define F4SE_MAKE_INCREMENTER_OP(a_op) \ - template \ - constexpr auto operator a_op##a_op(enumeration& a_lhs) noexcept \ - ->enumeration& \ - { \ - return a_lhs a_op## = static_cast(1); \ - } \ - \ - template \ - [[nodiscard]] constexpr auto operator a_op##a_op(enumeration& a_lhs, int) noexcept \ - ->enumeration \ - { \ - const auto tmp = a_lhs; \ - a_op##a_op a_lhs; \ - return tmp; \ - } - namespace F4SE { namespace stl { - template < - class E, - class U> - [[nodiscard]] constexpr auto operator~(enumeration a_enum) noexcept - -> enumeration - { - return static_cast(~static_cast(a_enum.get())); - } - - F4SE_MAKE_LOGICAL_OP(==, bool); - F4SE_MAKE_LOGICAL_OP(<=>, std::strong_ordering); - - F4SE_MAKE_ARITHMETIC_OP(<<); - F4SE_MAKE_ENUMERATION_OP(<<); - F4SE_MAKE_ARITHMETIC_OP(>>); - F4SE_MAKE_ENUMERATION_OP(>>); - - F4SE_MAKE_ENUMERATION_OP(|); - F4SE_MAKE_ENUMERATION_OP(&); - F4SE_MAKE_ENUMERATION_OP(^); - - F4SE_MAKE_ENUMERATION_OP(+); - F4SE_MAKE_ENUMERATION_OP(-); - - F4SE_MAKE_INCREMENTER_OP(+); // ++ - F4SE_MAKE_INCREMENTER_OP(-); // -- - template class atomic_ref : public std::atomic_ref @@ -713,11 +518,6 @@ namespace F4SE } } -#undef F4SE_MAKE_INCREMENTER_OP -#undef F4SE_MAKE_ENUMERATION_OP -#undef F4SE_MAKE_ARITHMETIC_OP -#undef F4SE_MAKE_LOGICAL_OP - namespace RE { using namespace std::literals; diff --git a/CommonLibF4/include/REX/REX.h b/CommonLibF4/include/REX/REX.h new file mode 100644 index 00000000..9bdc966f --- /dev/null +++ b/CommonLibF4/include/REX/REX.h @@ -0,0 +1,169 @@ +#pragma once + +namespace REX +{ + template < + class E, + class U = std::underlying_type_t> + class EnumSet + { + public: + using enum_type = E; + using underlying_type = U; + + static_assert(std::is_enum_v, "EnumSet must be an enum"); + static_assert(std::is_integral_v, "EnumSet<..., U> must be an integral"); + + constexpr EnumSet() noexcept = default; + constexpr EnumSet(const EnumSet&) noexcept = default; + constexpr EnumSet(EnumSet&&) noexcept = default; + + template // NOLINTNEXTLINE(google-explicit-constructor) + constexpr EnumSet(EnumSet a_rhs) noexcept : + _impl(static_cast(a_rhs.get())) + {} + + template + constexpr EnumSet(Args... a_values) noexcept + requires(std::same_as&&...) : + _impl((static_cast(a_values) | ...)) + {} + + ~EnumSet() noexcept = default; + + constexpr EnumSet& operator=(const EnumSet&) noexcept = default; + constexpr EnumSet& operator=(EnumSet&&) noexcept = default; + + template + constexpr EnumSet& operator=(EnumSet a_rhs) noexcept + { + _impl = static_cast(a_rhs.get()); + } + + constexpr EnumSet& operator=(E a_value) noexcept + { + _impl = static_cast(a_value); + return *this; + } + + public: + [[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast(0); } + + [[nodiscard]] constexpr E operator*() const noexcept { return get(); } + [[nodiscard]] constexpr E get() const noexcept { return static_cast(_impl); } + [[nodiscard]] constexpr U underlying() const noexcept { return _impl; } + + public: + template + constexpr EnumSet& set(Args... a_args) noexcept + requires(std::same_as&&...) + { + _impl |= (static_cast(a_args) | ...); + return *this; + } + + template + constexpr EnumSet& reset(Args... a_args) noexcept + requires(std::same_as&&...) + { + _impl &= ~(static_cast(a_args) | ...); + return *this; + } + + constexpr EnumSet& reset() noexcept + { + _impl = 0; + return *this; + } + + template + [[nodiscard]] constexpr bool any(Args... a_args) const noexcept + requires(std::same_as&&...) + { + return (_impl & (static_cast(a_args) | ...)) != static_cast(0); + } + + template + [[nodiscard]] constexpr bool all(Args... a_args) const noexcept + requires(std::same_as&&...) + { + return (_impl & (static_cast(a_args) | ...)) == (static_cast(a_args) | ...); + } + + template + [[nodiscard]] constexpr bool none(Args... a_args) const noexcept + requires(std::same_as&&...) + { + return (_impl & (static_cast(a_args) | ...)) == static_cast(0); + } + + public: + friend constexpr bool operator==(EnumSet a_lhs, EnumSet a_rhs) noexcept { return a_lhs.underlying() == a_rhs.underlying(); } + friend constexpr bool operator==(EnumSet a_lhs, E a_rhs) noexcept { return a_lhs.underlying() == static_cast(a_rhs); } + friend constexpr bool operator==(E a_lhs, EnumSet a_rhs) noexcept { return static_cast(a_lhs) == a_rhs.underlying(); } + + friend constexpr std::strong_ordering operator<=>(EnumSet a_lhs, EnumSet a_rhs) noexcept { return a_lhs.underlying() <=> a_rhs.underlying(); } + friend constexpr std::strong_ordering operator<=>(EnumSet a_lhs, E a_rhs) noexcept { return a_lhs.underlying() <=> static_cast(a_rhs); } + friend constexpr std::strong_ordering operator<=>(E a_lhs, EnumSet a_rhs) noexcept { return static_cast(a_lhs) <=> a_rhs.underlying(); } + + friend constexpr EnumSet operator&(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast(a_lhs.underlying() & a_rhs.underlying()); } + friend constexpr EnumSet operator&(EnumSet a_lhs, E a_rhs) noexcept { return static_cast(a_lhs.underlying() & static_cast(a_rhs)); } + friend constexpr EnumSet operator&(E a_lhs, EnumSet a_rhs) noexcept { return static_cast(static_cast(a_lhs) & a_rhs.underlying()); } + + friend constexpr EnumSet& operator&=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs & a_rhs; } + friend constexpr EnumSet& operator&=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs & a_rhs; } + + friend constexpr EnumSet operator|(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast(a_lhs.underlying() | a_rhs.underlying()); } + friend constexpr EnumSet operator|(EnumSet a_lhs, E a_rhs) noexcept { return static_cast(a_lhs.underlying() | static_cast(a_rhs)); } + friend constexpr EnumSet operator|(E a_lhs, EnumSet a_rhs) noexcept { return static_cast(static_cast(a_lhs) | a_rhs.underlying()); } + + friend constexpr EnumSet& operator|=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs | a_rhs; } + friend constexpr EnumSet& operator|=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs | a_rhs; } + + friend constexpr EnumSet operator^(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast(a_lhs.underlying() ^ a_rhs.underlying()); } + friend constexpr EnumSet operator^(EnumSet a_lhs, E a_rhs) noexcept { return static_cast(a_lhs.underlying() ^ static_cast(a_rhs)); } + friend constexpr EnumSet operator^(E a_lhs, EnumSet a_rhs) noexcept { return static_cast(static_cast(a_lhs) ^ a_rhs.underlying()); } + + friend constexpr EnumSet& operator^=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs ^ a_rhs; } + friend constexpr EnumSet& operator^=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs ^ a_rhs; } + + friend constexpr EnumSet operator+(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast(a_lhs.underlying() + a_rhs.underlying()); } + friend constexpr EnumSet operator+(EnumSet a_lhs, E a_rhs) noexcept { return static_cast(a_lhs.underlying() + static_cast(a_rhs)); } + friend constexpr EnumSet operator+(E a_lhs, EnumSet a_rhs) noexcept { return static_cast(static_cast(a_lhs) + a_rhs.underlying()); } + + friend constexpr EnumSet& operator+=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs + a_rhs; } + friend constexpr EnumSet& operator+=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs + a_rhs; } + + friend constexpr EnumSet operator-(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast(a_lhs.underlying() - a_rhs.underlying()); } + friend constexpr EnumSet operator-(EnumSet a_lhs, E a_rhs) noexcept { return static_cast(a_lhs.underlying() - static_cast(a_rhs)); } + friend constexpr EnumSet operator-(E a_lhs, EnumSet a_rhs) noexcept { return static_cast(static_cast(a_lhs) - a_rhs.underlying()); } + + friend constexpr EnumSet& operator-=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs - a_rhs; } + friend constexpr EnumSet& operator-=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs - a_rhs; } + + friend constexpr EnumSet operator<<(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast(a_lhs.underlying() << a_rhs.underlying()); } + friend constexpr EnumSet operator<<(EnumSet a_lhs, E a_rhs) noexcept { return static_cast(a_lhs.underlying() << static_cast(a_rhs)); } + friend constexpr EnumSet operator<<(E a_lhs, EnumSet a_rhs) noexcept { return static_cast(static_cast(a_lhs) << a_rhs.underlying()); } + + friend constexpr EnumSet& operator<<=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs << a_rhs; } + friend constexpr EnumSet& operator<<=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs << a_rhs; } + + friend constexpr EnumSet operator>>(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast(a_lhs.underlying() >> a_rhs.underlying()); } + friend constexpr EnumSet operator>>(EnumSet a_lhs, E a_rhs) noexcept { return static_cast(a_lhs.underlying() >> static_cast(a_rhs)); } + friend constexpr EnumSet operator>>(E a_lhs, EnumSet a_rhs) noexcept { return static_cast(static_cast(a_lhs) >> a_rhs.underlying()); } + + friend constexpr EnumSet& operator>>=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs >> a_rhs; } + friend constexpr EnumSet& operator>>=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs >> a_rhs; } + + friend constexpr EnumSet& operator~(EnumSet& a_lhs) noexcept { return a_lhs = ~a_lhs.underlying(); } + + private: + U _impl{ 0 }; + }; + + template + EnumSet(Args...) -> EnumSet< + std::common_type_t, + std::underlying_type_t< + std::common_type_t>>; +}