mirror of
https://github.com/Neargye/magic_enum.git
synced 2026-01-09 23:34:23 +00:00
add compile time enum_index (#159)
This commit is contained in:
parent
04a3d32d0f
commit
b0c0e02bdc
3 changed files with 56 additions and 28 deletions
|
|
@ -108,11 +108,14 @@ constexpr optional<E> enum_cast(string_view value, BinaryPredicate p) noexcept(i
|
|||
```cpp
|
||||
template <typename E>
|
||||
constexpr E enum_value(size_t index) noexcept;
|
||||
|
||||
template <typename E, size_t I>
|
||||
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<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<Color>(i);
|
||||
// color -> Color::BLUE
|
||||
````
|
||||
```
|
||||
|
||||
```cpp
|
||||
Color color = magic_enum::enum_value<Color, 1>();
|
||||
// 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<value>()` occurs the compilation error `"Enum value does not have a name."`.
|
||||
* If enum value does not have name, `enum_name<value>()` occurs the compilation error `magic_enum::enum_name enum value does not have a name`.
|
||||
|
||||
* `enum_name<value>()` 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>();
|
||||
// color_name -> "BLUE"
|
||||
```
|
||||
```cpp
|
||||
constexpr Color color = Color::BLUE;
|
||||
constexpr auto color_name = magic_enum::enum_name<color>();
|
||||
// color_name -> "BLUE"
|
||||
```
|
||||
|
||||
## `enum_flags_name`
|
||||
|
||||
|
|
@ -264,19 +268,27 @@ constexpr array<pair<E, string_view>, N> enum_entries() noexcept;
|
|||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr optional<size_t> enum_index() noexcept;
|
||||
constexpr optional<size_t> enum_index(E value) noexcept;
|
||||
|
||||
template <auto V>
|
||||
constexpr size_t enum_index() noexcept;
|
||||
```
|
||||
|
||||
* Obtains index in enum values from enum value.
|
||||
|
||||
* Returns `optional<size_t>` with index.
|
||||
* `enum_index(value)` returns `optional<size_t>` with index.
|
||||
* `enum_index<value>()` 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::BLUE>();
|
||||
// color_index -> 1
|
||||
```
|
||||
|
||||
## `enum_contains`
|
||||
|
|
@ -330,7 +342,7 @@ constexpr string_view enum_type_name() noexcept;
|
|||
|
||||
```cpp
|
||||
template <typename... Es>
|
||||
[[nodiscard]] constexpr optional<enum_fuse_t> enum_fuse(Es... values);
|
||||
[[nodiscard]] constexpr optional<enum_fuse_t> 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 <typename... Es>
|
|||
|
||||
* 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
|
||||
|
||||
|
|
|
|||
|
|
@ -661,7 +661,7 @@ using underlying_type_t = typename underlying_type<T>::type;
|
|||
template <typename E>
|
||||
[[nodiscard]] constexpr auto enum_type_name() noexcept -> detail::enable_if_enum_t<E, string_view> {
|
||||
constexpr string_view name = detail::type_name_v<std::decay_t<E>>;
|
||||
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 <typename E>
|
|||
// Returns enum value at specified index.
|
||||
template <typename E, std::size_t I>
|
||||
[[nodiscard]] constexpr auto enum_value() noexcept -> detail::enable_if_enum_t<E, std::decay_t<E>> {
|
||||
return enum_value<std::decay_t<E>>(I);
|
||||
using D = std::decay_t<E>;
|
||||
static_assert(I < detail::count_v<D>, "magic_enum::enum_value out of range.");
|
||||
|
||||
return enum_value<D>(I);
|
||||
}
|
||||
|
||||
// Returns std::array with enum values, sorted by enum value.
|
||||
|
|
@ -705,7 +708,7 @@ template <typename E>
|
|||
template <auto V>
|
||||
[[nodiscard]] constexpr auto enum_name() noexcept -> detail::enable_if_enum_t<decltype(V), string_view> {
|
||||
constexpr string_view name = detail::enum_name_v<std::decay_t<decltype(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 <typename E>
|
|||
return {}; // Invalid value or out of range.
|
||||
}
|
||||
|
||||
// Obtains index in enum values from static storage enum variable.
|
||||
template <auto V>
|
||||
[[nodiscard]] constexpr auto enum_index() noexcept -> detail::enable_if_enum_t<decltype(V), std::size_t> {
|
||||
constexpr auto index = enum_index<std::decay_t<decltype(V)>>(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 <typename E>
|
||||
[[nodiscard]] constexpr auto enum_contains(E value) noexcept -> detail::enable_if_enum_t<E, bool> {
|
||||
|
|
|
|||
|
|
@ -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<Color::RED>() == 0);
|
||||
REQUIRE(enum_index<Color&>(cg).value() == 1);
|
||||
REQUIRE(enum_index(cm[2]).value() == 2);
|
||||
REQUIRE_FALSE(enum_index(static_cast<Color>(0)).has_value());
|
||||
|
||||
constexpr auto no = enum_index(Numbers::one);
|
||||
REQUIRE(no.value() == 0);
|
||||
REQUIRE(enum_index<Numbers::one>() == 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<Directions::Left>() == 0);
|
||||
REQUIRE(enum_index<Directions&>(dl).value() == 0);
|
||||
REQUIRE(enum_index<const Directions>(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<number::one>() == 0);
|
||||
REQUIRE(enum_index(number::one).value() == 0);
|
||||
REQUIRE(enum_index(number::two).value() == 1);
|
||||
REQUIRE(nt.value() == 2);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue