diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 8073c9a..89b6eb2 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -280,6 +280,10 @@ constexpr bool cmp_less(L lhs, R rhs) noexcept { if constexpr (std::is_signed_v == std::is_signed_v) { // If same signedness (both signed or both unsigned). return lhs < rhs; + } else if constexpr (std::is_same_v) { // bool special case due to msvc's C4804, C4018 + return static_cast(lhs) < rhs; + } else if constexpr (std::is_same_v) { // bool special case due to msvc's C4804, C4018 + return lhs < static_cast(rhs); } else if constexpr (std::is_signed_v) { // If 'right' is negative, then result is 'false', otherwise cast & compare. return rhs > 0 && lhs < static_cast>(rhs); @@ -383,13 +387,11 @@ constexpr int reflected_min() noexcept { static_assert(lhs > (std::numeric_limits::min)(), "magic_enum::enum_range requires min must be greater than INT16_MIN."); constexpr auto rhs = (std::numeric_limits::min)(); - if constexpr (std::is_same_v) { - return static_cast(rhs); - } else if constexpr (cmp_less(lhs, rhs)) { - return rhs; - } else { + if constexpr (cmp_less(rhs, lhs)) { static_assert(!is_valid(0)>(), "magic_enum::enum_range detects enum value smaller than min range size."); return lhs; + } else { + return rhs; } } } @@ -405,9 +407,7 @@ constexpr int reflected_max() noexcept { static_assert(lhs < (std::numeric_limits::max)(), "magic_enum::enum_range requires max must be less than INT16_MAX."); constexpr auto rhs = (std::numeric_limits::max)(); - if constexpr (std::is_same_v) { - return static_cast(rhs); - } else if constexpr (cmp_less(lhs, rhs)) { + if constexpr (cmp_less(lhs, rhs)) { static_assert(!is_valid(0)>(), "magic_enum::enum_range detects enum value larger than max range size."); return lhs; } else { diff --git a/test/test.cpp b/test/test.cpp index 74f38f0..5a864c4 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -54,12 +54,30 @@ enum number : unsigned long { #endif }; +enum class MaxUsedAsInvalid : std::uint8_t { + ONE, + TWO, + INVALID = std::numeric_limits::max() +}; + enum class Binary : bool { ONE, TWO }; namespace magic_enum::customize { +template <> +struct enum_range { + static constexpr int min = 0; + static constexpr int max = 64; +}; + +template <> +struct enum_range { + static constexpr int min = 0; + static constexpr int max = 64; +}; + template <> struct enum_range { static constexpr int min = 100; @@ -341,6 +359,9 @@ TEST_CASE("enum_values") { constexpr auto& s5 = enum_values(); REQUIRE(s5 == std::array{{Binary::ONE, Binary::TWO}}); + + constexpr auto& s6 = enum_values(); + REQUIRE(s6 == std::array{{MaxUsedAsInvalid::ONE, MaxUsedAsInvalid::TWO}}); } TEST_CASE("enum_count") { @@ -358,6 +379,9 @@ TEST_CASE("enum_count") { constexpr auto s5 = enum_count(); REQUIRE(s5 == 2); + + constexpr auto s6 = enum_count(); + REQUIRE(s6 == 2); } TEST_CASE("enum_name") { @@ -427,6 +451,7 @@ TEST_CASE("enum_name") { REQUIRE(enum_name() == "four"); REQUIRE(enum_name() == "ONE"); + REQUIRE(enum_name() == "ONE"); } } @@ -664,6 +689,9 @@ TEST_CASE("extrema") { REQUIRE(magic_enum::detail::reflected_min_v == 0); REQUIRE(magic_enum::detail::min_v == false); + + REQUIRE(magic_enum::detail::reflected_min_v == 0); + REQUIRE(magic_enum::detail::min_v == 0); } SECTION("max") { @@ -689,6 +717,9 @@ TEST_CASE("extrema") { REQUIRE(magic_enum::detail::reflected_max_v == 1); REQUIRE(magic_enum::detail::max_v == true); + + REQUIRE(magic_enum::detail::reflected_max_v == 64); + REQUIRE(magic_enum::detail::max_v == 1); } } @@ -755,4 +786,16 @@ TEST_CASE("cmp_less") { REQUIRE_FALSE(cmp_less(uint32_t_min, int64_t_min + offset_int32_t)); REQUIRE_FALSE(cmp_less(uint64_t_min, int32_t_min + offset_int64_t)); } + + SECTION("bool, right") { + REQUIRE(cmp_less(true, 5)); + REQUIRE(cmp_less(false, 1)); + REQUIRE_FALSE(cmp_less(false, -1)); + } + + SECTION("left, bool") { + REQUIRE_FALSE(cmp_less(5, true)); + REQUIRE_FALSE(cmp_less(1, false)); + REQUIRE(cmp_less(-1, false)); + } }