diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 29a0c12..979dccd 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -58,7 +58,7 @@ namespace detail { template [[nodiscard]] constexpr std::optional enum_to_string_impl() noexcept { - static_assert(std::is_enum_v); + static_assert(std::is_enum_v, "magic_enum::enum_to_string require enum type."); #if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 9) std::string_view name{__PRETTY_FUNCTION__}; constexpr auto suffix = sizeof("]") - 1; @@ -89,7 +89,7 @@ template template struct enum_to_string_impl_t final { [[nodiscard]] constexpr std::optional operator()(int value) const noexcept { - static_assert(std::is_enum_v); + static_assert(std::is_enum_v, "magic_enum::enum_to_string require enum type."); if constexpr (V > std::numeric_limits>::max()) { return std::nullopt; // Enum variable out of range. } @@ -120,14 +120,52 @@ struct enum_to_string_impl_t final { template struct enum_to_string_impl_t final { [[nodiscard]] constexpr std::optional operator()(int) const noexcept { - static_assert(std::is_enum_v); + static_assert(std::is_enum_v, "magic_enum::enum_to_string require enum type."); + return std::nullopt; // Enum variable out of range MAGIC_ENUM_MAX_SEARCH_DEPTH. + } +}; + +template +struct enum_from_string_impl_t final { + [[nodiscard]] constexpr std::optional operator()(std::string_view name) const noexcept { + static_assert(std::is_enum_v, "magic_enum::enum_from_string require enum type."); + if constexpr (V > std::numeric_limits>::max()) { + return std::nullopt; // Enum variable out of range. + } + + if (enum_to_string_impl(V)>() == name) { + return static_cast(V); + } else if (enum_to_string_impl(V + 1)>() == name) { + return static_cast(V + 1); + } else if (enum_to_string_impl(V + 2)>() == name) { + return static_cast(V + 2); + } else if (enum_to_string_impl(V + 3)>() == name) { + return static_cast(V + 3); + } else if (enum_to_string_impl(V + 4)>() == name) { + return static_cast(V + 4); + } else if (enum_to_string_impl(V + 5)>() == name) { + return static_cast(V + 5); + } else if (enum_to_string_impl(V + 6)>() == name) { + return static_cast(V + 6); + } else if (enum_to_string_impl(V + 7)>() == name) { + return static_cast(V + 7); + } else { + return enum_from_string_impl_t{}(name); + } + } +}; + +template +struct enum_from_string_impl_t final { + [[nodiscard]] constexpr std::optional operator()(std::string_view) const noexcept { + static_assert(std::is_enum_v, "magic_enum::enum_from_string require enum type."); return std::nullopt; // Enum variable out of range MAGIC_ENUM_MAX_SEARCH_DEPTH. } }; } // namespace detail -// enum_to_string(value) used to obtain string enum name from enum variable. +// enum_to_string(enum) used to obtain string enum name from enum variable. template >>> [[nodiscard]] constexpr std::optional enum_to_string(T value) noexcept { constexpr bool s = std::is_signed_v>>; @@ -135,7 +173,7 @@ template return detail::enum_to_string_impl_t, min>{}(static_cast(value)); } -// enum_to_string() used to obtain string enum name from static storage enum variable +// enum_to_string() used to obtain string enum name from static storage enum variable template >>> [[nodiscard]] constexpr std::optional enum_to_string() noexcept { return detail::enum_to_string_impl(); @@ -146,13 +184,7 @@ template >> [[nodiscard]] constexpr std::optional enum_from_string(std::string_view name) noexcept { constexpr bool s = std::is_signed_v>; constexpr int min = s ? -MAGIC_ENUM_MAX_SEARCH_DEPTH : 0; - for (int i = min; i < MAGIC_ENUM_MAX_SEARCH_DEPTH; ++i) { - if (detail::enum_to_string_impl_t{}(i) == name) { - return static_cast(i); - } - } - - return std::nullopt; // Argument name has not been enum variable name. + return detail::enum_from_string_impl_t{}(name); } } // namespace magic_enum diff --git a/test/test.cpp b/test/test.cpp index eff30a5..444827e 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -34,7 +34,7 @@ enum Directions { Up = 85, Down = -42, Right = 119, Left = -119 }; enum number : int { one = 10, two = 20, three = 30 }; -TEST_CASE("magic_enum::enum_to_string(value)") { +TEST_CASE("magic_enum::enum_to_string(enum)") { Color cr = Color::RED; Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE}; REQUIRE(magic_enum::enum_to_string(cr).value() == "RED"); @@ -62,7 +62,7 @@ TEST_CASE("magic_enum::enum_to_string(value)") { REQUIRE(!magic_enum::enum_to_string(static_cast(MAGIC_ENUM_MAX_SEARCH_DEPTH)).has_value()); } -TEST_CASE("magic_enum::enum_to_string()") { +TEST_CASE("magic_enum::enum_to_string()") { constexpr Color cr = Color::RED; constexpr Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE}; REQUIRE(magic_enum::enum_to_string().value() == "RED");