diff --git a/doc/reference.md b/doc/reference.md index 742946a..7bb0f50 100644 --- a/doc/reference.md +++ b/doc/reference.md @@ -108,11 +108,14 @@ constexpr optional enum_cast(string_view value, BinaryPredicate p) noexcept(i ```cpp template constexpr E enum_value(size_t index) noexcept; + +template +constexpr E enum_value() noexcept; ``` * Returns enum value at specified index. - -* No bounds checking is performed: the behavior is undefined if `index >= number of enum values`. + * `enum_value(value)` no bounds checking is performed: the behavior is undefined if `index >= number of enum values`. + * `enum_value()` check if `I >= number of enum values`, occurs the compilation error `magic_enum::enum_value out of range`. * Examples @@ -120,7 +123,12 @@ constexpr E enum_value(size_t index) noexcept; int i = 1; Color color = magic_enum::enum_value(i); // color -> Color::BLUE - ```` + ``` + + ```cpp + Color color = magic_enum::enum_value(); + // color -> Color::BLUE + ``` ## `enum_values` @@ -184,27 +192,23 @@ constexpr string_view enum_name() noexcept; * Returns name from enum value as `string_view` with null-terminated string. * If enum value does not have name or [out of range](limitations.md), `enum_name(value)` returns empty string. - * If enum value does not have name, `enum_name()` occurs the compilation error `"Enum value does not have a name."`. + * If enum value does not have name, `enum_name()` occurs the compilation error `magic_enum::enum_name enum value does not have a name`. * `enum_name()` is much lighter on the compile times and is not restricted to the enum_range [limitation](limitations.md). * Examples - * Enum value to string. + ```cpp + Color color = Color::RED; + auto color_name = magic_enum::enum_name(color); + // color_name -> "RED" + ``` - ```cpp - Color color = Color::RED; - auto color_name = magic_enum::enum_name(color); - // color_name -> "RED" - ``` - - * Static storage enum variable to string. - - ```cpp - constexpr Color color = Color::BLUE; - constexpr auto color_name = magic_enum::enum_name(); - // color_name -> "BLUE" - ``` + ```cpp + constexpr Color color = Color::BLUE; + constexpr auto color_name = magic_enum::enum_name(); + // color_name -> "BLUE" + ``` ## `enum_flags_name` @@ -264,19 +268,27 @@ constexpr array, N> enum_entries() noexcept; ```cpp template -constexpr optional enum_index() noexcept; +constexpr optional enum_index(E value) noexcept; + +template +constexpr size_t enum_index() noexcept; ``` * Obtains index in enum values from enum value. - -* Returns `optional` with index. + * `enum_index(value)` returns `optional` with index. + * `enum_index()` returns index. If enum value does not have a index, occurs the compilation error `magic_enum::enum_index enum value does not have a index`. * Examples ```cpp constexpr auto color_index = magic_enum::enum_index(Color::BLUE); - // color_index -> color_index.value() -> 1 - // color_index -> color_index.has_value() -> true + // color_index.value() -> 1 + // color_index.has_value() -> true + ``` + + ```cpp + constexpr auto color_index = magic_enum::enum_index(); + // color_index -> 1 ``` ## `enum_contains` @@ -330,7 +342,7 @@ constexpr string_view enum_type_name() noexcept; ```cpp template -[[nodiscard]] constexpr optional enum_fuse(Es... values); +[[nodiscard]] constexpr optional enum_fuse(Es... values) noexcept; ``` * Returns a typesafe bijective mix of several enum values. This can be used to emulate 2D switch/case statements. @@ -339,7 +351,7 @@ template * Switch/case statement over an incomplete enum is a Visual Studio warning C4064 * You have to silent (/wd4064) or ignore it. - * Alternatively, define `MAGIC_ENUM_NO_TYPESAFE_ENUM_FUSE` to disable type-safety (`enum_fuse_t` equals `std::uintmax_t`). + * Alternatively, define `MAGIC_ENUM_NO_TYPESAFE_ENUM_FUSE` to disable type-safety (`enum_fuse_t` equals `uintmax_t`). * Examples diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 03dc557..139a614 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -661,7 +661,7 @@ using underlying_type_t = typename underlying_type::type; template [[nodiscard]] constexpr auto enum_type_name() noexcept -> detail::enable_if_enum_t { constexpr string_view name = detail::type_name_v>; - static_assert(name.size() > 0, "Enum type does not have a name."); + static_assert(!name.empty(), "magic_enum::enum_type_name enum type does not have a name."); return name; } @@ -691,7 +691,10 @@ template // Returns enum value at specified index. template [[nodiscard]] constexpr auto enum_value() noexcept -> detail::enable_if_enum_t> { - return enum_value>(I); + using D = std::decay_t; + static_assert(I < detail::count_v, "magic_enum::enum_value out of range."); + + return enum_value(I); } // Returns std::array with enum values, sorted by enum value. @@ -705,7 +708,7 @@ template template [[nodiscard]] constexpr auto enum_name() noexcept -> detail::enable_if_enum_t { constexpr string_view name = detail::enum_name_v, V>; - static_assert(name.size() > 0, "Enum value does not have a name."); + static_assert(!name.empty(), "magic_enum::enum_name enum value does not have a name."); return name; } @@ -888,6 +891,15 @@ template return {}; // Invalid value or out of range. } +// Obtains index in enum values from static storage enum variable. +template +[[nodiscard]] constexpr auto enum_index() noexcept -> detail::enable_if_enum_t { + constexpr auto index = enum_index>(V); + static_assert(index.has_value(), "magic_enum::enum_index enum value does not have a index."); + + return index.value(); +} + // Checks whether enum contains enumerator with such enum value. template [[nodiscard]] constexpr auto enum_contains(E value) noexcept -> detail::enable_if_enum_t { diff --git a/test/test.cpp b/test/test.cpp index 84fea6e..cfe0608 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -230,12 +230,14 @@ TEST_CASE("enum_index") { constexpr auto cr = enum_index(Color::RED); Color cg = Color::GREEN; REQUIRE(cr.value() == 0); + REQUIRE(enum_index() == 0); REQUIRE(enum_index(cg).value() == 1); REQUIRE(enum_index(cm[2]).value() == 2); REQUIRE_FALSE(enum_index(static_cast(0)).has_value()); constexpr auto no = enum_index(Numbers::one); REQUIRE(no.value() == 0); + REQUIRE(enum_index() == 0); REQUIRE(enum_index(Numbers::two).value() == 1); REQUIRE(enum_index(Numbers::three).value() == 2); REQUIRE_FALSE(enum_index(Numbers::many).has_value()); @@ -243,6 +245,7 @@ TEST_CASE("enum_index") { constexpr auto dr = enum_index(Directions::Right); Directions dl = Directions::Left; + REQUIRE(enum_index() == 0); REQUIRE(enum_index(dl).value() == 0); REQUIRE(enum_index(Directions::Down).value() == 1); REQUIRE(enum_index(Directions::Up).value() == 2); @@ -260,6 +263,7 @@ TEST_CASE("enum_index") { #endif constexpr auto nt = enum_index(number::three); + REQUIRE(enum_index() == 0); REQUIRE(enum_index(number::one).value() == 0); REQUIRE(enum_index(number::two).value() == 1); REQUIRE(nt.value() == 2);