diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index e9b5c0c..42ed589 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -78,18 +78,20 @@ static_assert(MAGIC_ENUM_RANGE_MIN > std::numeric_limits::min(), namespace detail { -template > +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; } -template > +template [[nodiscard]] constexpr auto range_impl() { static_assert(std::is_enum_v, "magic_enum::detail::range_impl requires enum type."); 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>{}; @@ -176,7 +178,7 @@ template } template -using enable_if_enum_t = typename std::enable_if>>::type; +using enable_if_enum_t = std::enable_if_t>>; template> struct is_scoped_enum_impl : std::false_type {}; @@ -209,12 +211,14 @@ template inline constexpr bool is_scoped_enum_v = is_scoped_enum::value; // Obtains enum value from enum string name. +// Returns std::optional with enum value. template > -[[nodiscard]] constexpr std::optional enum_cast(std::string_view value) noexcept { - static_assert(std::is_enum_v, "magic_enum::enum_cast requires enum type."); - constexpr auto values = detail::values_impl(detail::range_impl()); +[[nodiscard]] constexpr std::optional> enum_cast(std::string_view value) noexcept { + using D = std::decay_t; + static_assert(std::is_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 names = detail::names_impl(std::make_index_sequence{}); for (std::size_t i = 0; i < count; ++i) { if (names[i] == value) { @@ -226,14 +230,16 @@ template > } // Obtains enum value from integer value. +// Returns std::optional with enum value. template > -[[nodiscard]] constexpr std::optional enum_cast(std::underlying_type_t value) noexcept { - static_assert(std::is_enum_v, "magic_enum::enum_cast requires enum type."); +[[nodiscard]] constexpr std::optional> enum_cast(std::underlying_type_t> value) noexcept { + using D = std::decay_t; + static_assert(std::is_enum_v, "magic_enum::enum_cast requires enum type."); - if (detail::name_impl(static_cast(value)).empty()) { + if (detail::name_impl(static_cast(value)).empty()) { return std::nullopt; // Invalid value or out of range. } else { - return static_cast(value); + return static_cast(value); } } @@ -249,32 +255,36 @@ template > // Returns enum value at specified index. // No bounds checking is performed: the behavior is undefined if index >= number of enum values. template> -[[nodiscard]] constexpr E enum_value(std::size_t index) { - static_assert(std::is_enum_v, "magic_enum::enum_value requires enum type."); - constexpr auto values = detail::values_impl(detail::range_impl()); +[[nodiscard]] constexpr auto enum_value(std::size_t index) { + using D = std::decay_t; + static_assert(std::is_enum_v, "magic_enum::enum_value requires enum type."); + constexpr auto values = detail::values_impl(detail::range_impl()); return assert(index < values.size()), values[index]; } // Obtains value enum sequence. +// Returns std::array with enum values, sorted by enum value. template > [[nodiscard]] constexpr auto enum_values() noexcept { - static_assert(std::is_enum_v, "magic_enum::enum_values requires enum type."); - constexpr auto values = detail::values_impl(detail::range_impl()); + using D = std::decay_t; + static_assert(std::is_enum_v, "magic_enum::enum_values requires enum type."); + constexpr auto values = detail::values_impl(detail::range_impl()); return values; } // Returns number of enum values. template > -[[nodiscard]] constexpr std::size_t enum_count() noexcept { - static_assert(std::is_enum_v, "magic_enum::enum_count requires enum type."); - constexpr auto count = detail::values_impl(detail::range_impl()).size(); +[[nodiscard]] constexpr auto enum_count() noexcept { + using D = std::decay_t; + static_assert(std::is_enum_v, "magic_enum::enum_count requires enum type."); + constexpr auto count = detail::values_impl(detail::range_impl()).size(); return count; } -// Obtains string enum name from enum value. +// Returns string enum name from enum value. template > [[nodiscard]] constexpr std::string_view enum_name(E value) noexcept { using D = std::decay_t; @@ -284,21 +294,25 @@ template > } // Obtains string enum name sequence. +// Returns std::array with string enum names, sorted by enum value. template > [[nodiscard]] constexpr auto enum_names() noexcept { - static_assert(std::is_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{}); + using D = std::decay_t; + static_assert(std::is_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{}); return names; } // Obtains pair (value enum, string enum name) sequence. +// Returns std::array with std::pair (value enum, string enum name), sorted by enum value. template > [[nodiscard]] constexpr auto enum_entries() noexcept { - static_assert(std::is_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{}); + using D = std::decay_t; + static_assert(std::is_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{}); return entries; }