From cee99df7b5d0801d97c1951b304fa5f59b415e3b Mon Sep 17 00:00:00 2001 From: Daniil Goncharov Date: Mon, 28 Mar 2022 18:55:25 +0400 Subject: [PATCH] fix bool (#172) --- doc/reference.md | 3 +++ include/magic_enum.hpp | 36 +++++++++++++++++++++++++++--------- test/test.cpp | 25 +++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/doc/reference.md b/doc/reference.md index 665e7a7..97894f1 100644 --- a/doc/reference.md +++ b/doc/reference.md @@ -170,6 +170,9 @@ constexpr size_t enum_count() noexcept; ```cpp template constexpr underlying_type_t enum_integer(E value) noexcept; + +template +constexpr underlying_type_t enum_underlying(E value) noexcept; ``` * Returns integer value from enum value. diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 4856164..d2e015d 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -351,10 +351,14 @@ template constexpr I log2(I value) noexcept { static_assert(std::is_integral_v, "magic_enum::detail::log2 requires integral type."); - auto ret = I{0}; - for (; value > I{1}; value >>= I{1}, ++ret) {} + if constexpr (std::is_same_v) { // bool special case + return assert(false), value; + } else { + auto ret = I{0}; + for (; value > I{1}; value >>= I{1}, ++ret) {} - return ret; + return ret; + } } template @@ -597,11 +601,18 @@ using entries_t = decltype((entries_v)); template > constexpr bool is_sparse() noexcept { static_assert(is_enum_v, "magic_enum::detail::is_sparse requires enum type."); - constexpr auto max = is_flags_v ? log2(max_v) : max_v; - constexpr auto min = is_flags_v ? log2(min_v) : min_v; - constexpr auto range_size = max - min + 1; - return range_size != count_v && count_v > 0; + if constexpr (count_v == 0) { + return false; + } else if constexpr (std::is_same_v) { // bool special case + return false; + } else { + constexpr auto max = is_flags_v ? log2(max_v) : max_v; + constexpr auto min = is_flags_v ? log2(min_v) : min_v; + constexpr auto range_size = max - min + 1; + + return range_size != count_v; + } } template @@ -660,8 +671,8 @@ template struct constexpr_hash_t>> { constexpr auto operator()(Value value) const noexcept { using U = typename underlying_type::type; - if constexpr (std::is_same_v) { - return static_cast(static_cast(value)); + if constexpr (std::is_same_v) { // bool special case + return static_cast(value); } else { return static_cast(value); } @@ -961,6 +972,13 @@ template return static_cast>(value); } + +// Returns underlying value from enum value. +template +[[nodiscard]] constexpr auto enum_underlying(E value) noexcept -> detail::enable_if_enum_t> { + return static_cast>(value); +} + // Obtains index in enum values from enum value. // Returns optional with index. template diff --git a/test/test.cpp b/test/test.cpp index 34ae993..8319cf5 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -103,6 +103,8 @@ struct magic_enum::customize::enum_range { static constexpr int max = 64; }; +enum class BoolTest : bool { Yay, Nay }; + using namespace magic_enum; static_assert(is_magic_enum_supported, "magic_enum: Unsupported compiler (https://github.com/Neargye/magic_enum#compiler-compatibility)."); @@ -157,6 +159,8 @@ TEST_CASE("enum_cast") { constexpr auto crc = magic_enum::enum_cast("b5a7b602ab754d7ab30fb42c4fb28d82"); REQUIRE(crc.value() == crc_hack_2::b5a7b602ab754d7ab30fb42c4fb28d82); REQUIRE(magic_enum::enum_cast("d19f2e9e82d14b96be4fa12b8a27ee9f").value() == crc_hack_2::d19f2e9e82d14b96be4fa12b8a27ee9f); + + REQUIRE(magic_enum::enum_cast("Nay").has_value()); } SECTION("integer") { @@ -196,6 +200,9 @@ TEST_CASE("enum_cast") { REQUIRE(nt.value() == number::three); REQUIRE_FALSE(enum_cast(400).has_value()); REQUIRE_FALSE(enum_cast(0).has_value()); + + REQUIRE(enum_cast(false).has_value()); + REQUIRE(enum_cast(0).has_value()); } } @@ -239,6 +246,8 @@ TEST_CASE("enum_integer") { REQUIRE(nt == 300); REQUIRE(enum_integer(number::four) == 400); REQUIRE(enum_integer(static_cast(0)) == 0); + + REQUIRE(enum_integer(BoolTest::Yay) == false); } TEST_CASE("enum_index") { @@ -285,6 +294,8 @@ TEST_CASE("enum_index") { REQUIRE(nt.value() == 2); REQUIRE_FALSE(enum_index(number::four).has_value()); REQUIRE_FALSE(enum_index(static_cast(0)).has_value()); + + REQUIRE(enum_index() == 0); } TEST_CASE("enum_contains") { @@ -328,6 +339,8 @@ TEST_CASE("enum_contains") { REQUIRE(nt); REQUIRE_FALSE(enum_contains(number::four)); REQUIRE_FALSE(enum_contains(static_cast(0))); + + REQUIRE(enum_contains(BoolTest::Yay)); } SECTION("integer") { @@ -368,6 +381,9 @@ TEST_CASE("enum_contains") { REQUIRE_FALSE(enum_contains(number::four)); REQUIRE_FALSE(enum_contains(111)); REQUIRE_FALSE(enum_contains(0)); + + REQUIRE(enum_contains(false)); + REQUIRE(enum_contains(0)); } SECTION("string") { @@ -412,6 +428,8 @@ TEST_CASE("enum_contains") { REQUIRE(nt); REQUIRE_FALSE(enum_contains("four")); REQUIRE_FALSE(enum_contains("None")); + + REQUIRE(enum_contains("Yay")); } } @@ -461,6 +479,9 @@ TEST_CASE("enum_value") { REQUIRE(enum_value() == number::one); REQUIRE(enum_value() == number::two); REQUIRE(enum_value() == number::three); + + REQUIRE(enum_value(0) == BoolTest::Yay); + REQUIRE(enum_value() == BoolTest::Yay); } TEST_CASE("enum_values") { @@ -1101,7 +1122,7 @@ TEST_CASE("constexpr_for") { }); } -#ifdef _MSC_VER +#if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 4064) #endif @@ -1130,7 +1151,7 @@ static int switch_case_3d(Color color, Directions direction, Index index) { } } -#ifdef _MSC_VER +#if defined(_MSC_VER) # pragma warning(pop) #endif