Skip to content

Commit

Permalink
#134: Implement remaining enum operators, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ZehMatt committed Jun 30, 2024
1 parent edd30ff commit e6b521b
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
1 change: 1 addition & 0 deletions CMakeLists.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 65 additions & 0 deletions tests/src/tests/tests.enumflags.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <gtest/gtest.h>
#include <zasm/core/enumflags.hpp>

enum class TestFlags : std::uint32_t
{
none = 0,
a = 1U << 0,
b = 1U << 2,
c = 1U << 4,
d = 1U << 8,
e = 1U << 16,
f = 1U << 24,
g = 1U << 31,
};
ZASM_ENABLE_ENUM_OPERATORS(TestFlags);

TEST(EnumFlagsTest, operatorOr)
{
constexpr TestFlags flags = TestFlags::a | TestFlags::c | TestFlags::d | TestFlags::g;
constexpr auto value = static_cast<std::underlying_type_t<TestFlags>>(flags);
ASSERT_EQ(value, 0b1000'0000'0000'0000'0000'0001'0001'0001);
}

TEST(EnumFlagsTest, operatorAnd)
{
constexpr TestFlags flags = (TestFlags::a | TestFlags::c | TestFlags::d | TestFlags::g) & TestFlags::c;
constexpr auto value = static_cast<std::underlying_type_t<TestFlags>>(flags);
ASSERT_EQ(value, 0b0000'0000'0000'0000'0000'0000'0001'0000);
}

TEST(EnumFlagsTest, operatorXor)
{
constexpr TestFlags flags = (TestFlags::a | TestFlags::c | TestFlags::d) ^ (TestFlags::a | TestFlags::c | TestFlags::d)
^ TestFlags::f;
constexpr auto value = static_cast<std::underlying_type_t<TestFlags>>(flags);
ASSERT_EQ(value, 0b0000'0001'0000'0000'0000'0000'0000'0000);
}

TEST(EnumFlagsTest, operatorOrInplace)
{
TestFlags flags = TestFlags::none;
flags |= TestFlags::a;
flags |= TestFlags::c;
flags |= TestFlags::d;
flags |= TestFlags::g;
auto value = static_cast<std::underlying_type_t<TestFlags>>(flags);
ASSERT_EQ(value, 0b1000'0000'0000'0000'0000'0001'0001'0001);
}

TEST(EnumFlagsTest, operatorAndInplace)
{
TestFlags flags = (TestFlags::a | TestFlags::c | TestFlags::d | TestFlags::g);
flags &= TestFlags::c;
auto value = static_cast<std::underlying_type_t<TestFlags>>(flags);
ASSERT_EQ(value, 0b0000'0000'0000'0000'0000'0000'0001'0000);
}

TEST(EnumFlagsTest, operatorXorInplace)
{
TestFlags flags = (TestFlags::a | TestFlags::c | TestFlags::d);
flags ^= (TestFlags::a | TestFlags::c | TestFlags::d);
flags ^= TestFlags::f;
auto value = static_cast<std::underlying_type_t<TestFlags>>(flags);
ASSERT_EQ(value, 0b0000'0001'0000'0000'0000'0000'0000'0000);
}
17 changes: 16 additions & 1 deletion zasm/include/zasm/core/enumflags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,34 @@ namespace zasm
/// </summary>
/// <typeparam name="ENM">Enum type</typeparam>
#define ZASM_ENABLE_ENUM_OPERATORS(ENM) \
static_assert(std::is_unsigned_v<std::underlying_type_t<ENM>> == true, "Underlying enum type must be unsignd"); \
static_assert(std::is_unsigned_v<std::underlying_type_t<ENM>> == true, "Underlying enum type must be unsigned"); \
inline constexpr ENM operator|(const ENM a, const ENM b) noexcept \
{ \
return static_cast<ENM>(static_cast<std::underlying_type_t<ENM>>(a) | static_cast<std::underlying_type_t<ENM>>(b)); \
} \
inline constexpr ENM operator|=(ENM& a, const ENM b) noexcept \
{ \
a = static_cast<ENM>(static_cast<std::underlying_type_t<ENM>>(a) | static_cast<std::underlying_type_t<ENM>>(b)); \
return a; \
} \
inline constexpr ENM operator^(const ENM a, const ENM b) noexcept \
{ \
return static_cast<ENM>(static_cast<std::underlying_type_t<ENM>>(a) ^ static_cast<std::underlying_type_t<ENM>>(b)); \
} \
inline constexpr ENM operator^=(ENM& a, const ENM b) noexcept \
{ \
a = static_cast<ENM>(static_cast<std::underlying_type_t<ENM>>(a) ^ static_cast<std::underlying_type_t<ENM>>(b)); \
return a; \
} \
inline constexpr ENM operator&(const ENM a, const ENM b) noexcept \
{ \
return static_cast<ENM>(static_cast<std::underlying_type_t<ENM>>(a) & static_cast<std::underlying_type_t<ENM>>(b)); \
} \
inline constexpr ENM operator&=(ENM& a, const ENM b) noexcept \
{ \
a = static_cast<ENM>(static_cast<std::underlying_type_t<ENM>>(a) & static_cast<std::underlying_type_t<ENM>>(b)); \
return a; \
} \
inline constexpr ENM operator~(const ENM a) noexcept \
{ \
return static_cast<ENM>(~static_cast<std::underlying_type_t<ENM>>(a)); \
Expand Down

0 comments on commit e6b521b

Please sign in to comment.