diff --git a/lib/utils/mu-utils.hh b/lib/utils/mu-utils.hh index c4656890..a1c8979a 100644 --- a/lib/utils/mu-utils.hh +++ b/lib/utils/mu-utils.hh @@ -1,5 +1,5 @@ /* -** Copyright (C) 2020-2025 Dirk-Jan C. Binnema +** Copyright (C) 2020-2026 Dirk-Jan C. Binnema ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public License @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -673,23 +674,48 @@ private: #define MU_COLOR_DEFAULT "\x1b[0m" -/// Allow using enum structs as bitflags -#define MU_TO_NUM(ET, ELM) std::underlying_type_t(ELM) -#define MU_TO_ENUM(ET, NUM) static_cast(NUM) -#define MU_ENABLE_BITOPS(ET) \ - constexpr ET operator&(ET e1, ET e2) { \ - return MU_TO_ENUM(ET, MU_TO_NUM(ET, e1) & MU_TO_NUM(ET, e2)); \ - } \ - constexpr ET operator|(ET e1, ET e2) { \ - return MU_TO_ENUM(ET, MU_TO_NUM(ET, e1) | MU_TO_NUM(ET, e2)); \ - } \ - constexpr ET operator~(ET e) { return MU_TO_ENUM(ET, ~(MU_TO_NUM(ET, e))); } \ - constexpr bool any_of(ET e) { return MU_TO_NUM(ET, e) != 0; } \ - constexpr bool none_of(ET e) { return MU_TO_NUM(ET, e) == 0; } \ - constexpr bool one_of(ET e1, ET e2) { return (e1 & e2) == e2; } \ - constexpr ET& operator&=(ET& e1, ET e2) { return e1 = e1 & e2; } \ - constexpr ET& operator|=(ET& e1, ET e2) { return e1 = e1 | e2; } \ - static_assert(1==1) // require a semicolon +template // like C++23 std::to_underlying +constexpr std::underlying_type_t to_ut( Enum e ) noexcept { + return static_cast>(e); +} + +// C++20 way to make enum-class bitmaps usable + +template +requires std::is_enum_v +struct enable_bitops { + static constexpr bool enable = false; +}; +// add a concept EnumBitmap which work for enum-classes that specialize enable_bitmups +template concept EnumBitmap = enable_bitops::enable; + +template constexpr Enum operator|(Enum e1, Enum e2) { + return static_cast(to_ut(e1) | to_ut(e2)); +} +template constexpr Enum operator|=(Enum& e1, Enum e2) { + return e1 = static_cast(e1 | e2); +} +template constexpr Enum operator&=(Enum& e1, Enum e2) { + return e1 = static_cast(e1 & e2); +} +template constexpr Enum operator&(Enum e1, Enum e2) { + return static_cast(to_ut(e1) & to_ut(e2)); +} +template constexpr Enum operator~(Enum e) { + return static_cast(~to_ut(e)); +} +template constexpr bool any_of(Enum e) { + return to_ut(e) != 0; +} +template constexpr bool none_of(Enum e) { + return to_ut(e) == 0; +} + +#define MU_ENABLE_BITOPS(Enum) \ + template<> \c + struct enable_bitops { \ + static constexpr bool enable = true; \ + } } // namespace Mu diff --git a/lib/utils/tests/test-utils.cc b/lib/utils/tests/test-utils.cc index 195f996b..2e5aa47d 100644 --- a/lib/utils/tests/test-utils.cc +++ b/lib/utils/tests/test-utils.cc @@ -260,12 +260,16 @@ test_join() } +namespace Mu { enum struct Bits { None = 0, Bit1 = 1 << 0, Bit2 = 1 << 1 }; MU_ENABLE_BITOPS(Bits); +} static void test_define_bitmap() { + using namespace Mu; + g_assert_cmpuint((guint)Bits::None, ==, (guint)0); g_assert_cmpuint((guint)Bits::Bit1, ==, (guint)1); g_assert_cmpuint((guint)Bits::Bit2, ==, (guint)2);