diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 12c1abd..cdf85c3 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -83,13 +83,9 @@ static_assert(MAGIC_ENUM_RANGE_MAX > MAGIC_ENUM_RANGE_MIN, namespace detail { template -[[nodiscard]] constexpr int min_impl() { - static_assert(std::is_enum_v, "magic_enum::detail::min_impl requires enum type."); - using U = std::underlying_type_t; - constexpr int min = enum_range::min > (std::numeric_limits::min)() ? enum_range::min : (std::numeric_limits::min)(); - - return min; -} +inline constexpr auto min_v = enum_range::min > (std::numeric_limits>::min)() + ? enum_range::min + : (std::numeric_limits>::min)(); template [[nodiscard]] constexpr auto range_impl() { @@ -98,12 +94,14 @@ template static_assert(enum_range::max < (std::numeric_limits::max)(), "magic_enum::enum_range requires max must be less than INT_MAX."); static_assert(enum_range::max > enum_range::min, "magic_enum::enum_range requires max > min."); using U = std::underlying_type_t; - constexpr int max = enum_range::max < (std::numeric_limits::max)() ? enum_range::max : (std::numeric_limits::max)(); - constexpr auto range = std::make_integer_sequence() + 1>{}; + constexpr auto max = enum_range::max < (std::numeric_limits::max)() ? enum_range::max : (std::numeric_limits::max)(); - return range; + return std::make_integer_sequence + 1>{}; } +template +inline constexpr auto range_v = range_impl(); + [[nodiscard]] constexpr std::string_view pretty_name(std::string_view name) noexcept { for (std::size_t i = name.length(); i > 0; --i) { if (!((name[i - 1] >= '0' && name[i - 1] <= '9') || @@ -128,33 +126,33 @@ template [[nodiscard]] constexpr std::string_view name_impl() noexcept { static_assert(std::is_enum_v, "magic_enum::detail::name_impl requires enum type."); #if defined(__clang__) - constexpr auto name = pretty_name({__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 2}); + return pretty_name({__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 2}); #elif defined(__GNUC__) && __GNUC__ >= 9 - constexpr auto name = pretty_name({__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 51}); + return pretty_name({__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 51}); #elif defined(_MSC_VER) - constexpr auto name = pretty_name({__FUNCSIG__, sizeof(__FUNCSIG__) - 17}); + return pretty_name({__FUNCSIG__, sizeof(__FUNCSIG__) - 17}); #else - constexpr std::string_view name; // Unsupported compiler. + return {}; // Unsupported compiler. #endif - - return name; } template [[nodiscard]] constexpr auto strings_impl(std::integer_sequence) noexcept { static_assert(std::is_enum_v, "magic_enum::detail::strings_impl requires enum type."); - constexpr std::array names{{name_impl(I + min_impl())>()...}}; - return names; + return std::array{{name_impl(I + min_v)>()...}}; } +template +inline constexpr auto strings_v = strings_impl(range_v); + template [[nodiscard]] constexpr std::string_view name_impl(int value) noexcept { static_assert(std::is_enum_v, "magic_enum::detail::name_impl requires enum type."); - constexpr auto names = strings_impl(range_impl()); + constexpr auto strings = strings_v; - if (auto i = static_cast((value - min_impl())); i < names.size()) { - return names[i]; + if (auto i = static_cast((value - min_v)); i < strings.size()) { + return strings[i]; } return {}; // Value out of range. @@ -163,37 +161,45 @@ template template [[nodiscard]] constexpr auto values_impl(std::integer_sequence) noexcept { static_assert(std::is_enum_v, "magic_enum::detail::values_impl requires enum type."); - constexpr std::array valid{{!name_impl(I + min_impl())>().empty()...}}; + constexpr std::array valid{{!name_impl(I + min_v)>().empty()...}}; constexpr auto num_valid = ((valid[I] ? 1 : 0) + ...); std::array values{}; for (std::size_t i = 0, v = 0; i < valid.size() && v < num_valid; ++i) { if (valid[i]) { - values[v++] = static_cast(static_cast(i) + min_impl()); + values[v++] = static_cast(static_cast(i) + min_v); } } return values; } +template +inline constexpr auto values_v = values_impl(range_v); + +template +inline constexpr auto count_v = values_v.size(); + template [[nodiscard]] constexpr auto names_impl(std::integer_sequence) noexcept { static_assert(std::is_enum_v, "magic_enum::detail::names_impl requires enum type."); - constexpr auto values = values_impl(range_impl()); - constexpr std::array names{{name_impl()...}}; - return names; + return std::array{{name_impl[I]>()...}}; } +template +inline constexpr auto names_v = names_impl(std::make_index_sequence>{}); + template [[nodiscard]] constexpr auto entries_impl(std::integer_sequence) noexcept { static_assert(std::is_enum_v, "magic_enum::detail::entries_impl requires enum type."); - constexpr auto values = values_impl(range_impl()); - constexpr std::array, sizeof...(I)> entries{{{values[I], name_impl()}...}}; - return entries; + return std::array, sizeof...(I)>{{{values_v[I], names_v[I]}...}}; } +template +inline constexpr auto entries_v = entries_impl(std::make_index_sequence>{}); + template using remove_cvref_t = std::remove_cv_t>; @@ -266,9 +272,9 @@ using underlying_type_t = typename underlying_type::type; template > [[nodiscard]] constexpr std::optional enum_cast(std::string_view value) noexcept { static_assert(detail::check_enum_v, "magic_enum::enum_cast requires enum type."); - constexpr auto values = detail::values_impl(detail::range_impl()); - constexpr auto count = values.size(); - constexpr auto names = detail::names_impl(std::make_index_sequence{}); + constexpr auto values = detail::values_v; + constexpr auto count = detail::count_v; + constexpr auto names = detail::names_v; for (std::size_t i = 0; i < count; ++i) { if (names[i] == value) { @@ -305,7 +311,7 @@ template > template> [[nodiscard]] constexpr auto enum_value(std::size_t index) { static_assert(detail::check_enum_v, "magic_enum::enum_value requires enum type."); - constexpr auto values = detail::values_impl(detail::range_impl()); + constexpr auto values = detail::values_v; return assert(index < values.size()), values[index]; } @@ -315,7 +321,7 @@ template> template > [[nodiscard]] constexpr auto enum_values() noexcept { static_assert(detail::check_enum_v, "magic_enum::enum_values requires enum type."); - constexpr auto values = detail::values_impl(detail::range_impl()); + constexpr auto values = detail::values_v; return values; } @@ -324,7 +330,7 @@ template > template > [[nodiscard]] constexpr std::size_t enum_count() noexcept { static_assert(detail::check_enum_v, "magic_enum::enum_count requires enum type."); - constexpr std::size_t count = detail::values_impl(detail::range_impl()).size(); + constexpr auto count = detail::count_v; return count; } @@ -351,8 +357,7 @@ template > template > [[nodiscard]] constexpr auto enum_names() noexcept { static_assert(detail::check_enum_v, "magic_enum::enum_names requires enum type."); - constexpr auto count = detail::values_impl(detail::range_impl()).size(); - constexpr auto names = detail::names_impl(std::make_index_sequence{}); + constexpr auto names = detail::names_v; return names; } @@ -362,8 +367,7 @@ template > template > [[nodiscard]] constexpr auto enum_entries() noexcept { static_assert(detail::check_enum_v, "magic_enum::enum_entries requires enum type."); - constexpr auto count = detail::values_impl(detail::range_impl()).size(); - constexpr auto entries = detail::entries_impl(std::make_index_sequence{}); + constexpr auto entries = detail::entries_v; return entries; }