mirror of
https://github.com/Neargye/magic_enum.git
synced 2026-01-09 23:34:23 +00:00
Introduce contains_value()
* split enum_traits index * add more proper way to check if enum contains certain value * change description of contains_value() and add it in readme
This commit is contained in:
parent
1e6c9a5a5a
commit
aa24461613
3 changed files with 47 additions and 4 deletions
|
|
@ -32,6 +32,7 @@ Header-only C++17 library provides static reflection for enums, work with any en
|
|||
* `enum_names` obtains string enum name sequence.
|
||||
* `enum_entries` obtains pair (value enum, string enum name) sequence.
|
||||
* `enum_index` obtains index in enum value sequence from enum value.
|
||||
* `contains_value` checks whether enum contains such value
|
||||
* `is_unscoped_enum` checks whether type is an [Unscoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration).
|
||||
* `is_scoped_enum` checks whether type is an [Scoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations).
|
||||
* `underlying_type` improved UB-free "SFINAE-friendly" [std::underlying_type](https://en.cppreference.com/w/cpp/types/underlying_type).
|
||||
|
|
|
|||
|
|
@ -359,20 +359,24 @@ struct enum_traits<E, true> {
|
|||
return static_cast<U>(value) >= static_cast<U>(reflected_min_v<E>) && static_cast<U>(value) <= static_cast<U>(reflected_max_v<E>);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr int index(E value) noexcept {
|
||||
if (static_cast<U>(value) >= static_cast<U>(min_v<E>) && static_cast<U>(value) <= static_cast<U>(max_v<E>)) {
|
||||
[[nodiscard]] static constexpr int index(underlying_type value) noexcept {
|
||||
if (value >= min_v<E> && value <= max_v<E>) {
|
||||
if constexpr (is_sparse) {
|
||||
if (const auto i = indexes[static_cast<U>(value) - min_v<E>]; i != invalid_index_v<E>) {
|
||||
if (const auto i = indexes[value - min_v<E>]; i != invalid_index_v<E>) {
|
||||
return i;
|
||||
}
|
||||
} else {
|
||||
return static_cast<U>(value) - min_v<E>;
|
||||
return value - min_v<E>;
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // Value out of range.
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr int index(E value) noexcept {
|
||||
return index(static_cast<U>(value));
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr E value(std::size_t index) noexcept {
|
||||
if constexpr (is_sparse) {
|
||||
return assert(index < count), values[index];
|
||||
|
|
@ -486,6 +490,12 @@ template <typename E>
|
|||
return std::nullopt; // Value out of range.
|
||||
}
|
||||
|
||||
// Checks whether enum contains enumerator with such value
|
||||
template <typename E>
|
||||
[[nodiscard]] constexpr auto contains_value(underlying_type_t<E> value) noexcept -> detail::enable_if_enum_t<E, bool> {
|
||||
return enum_traits<E>::index(value) != -1;
|
||||
}
|
||||
|
||||
// Returns enum value at specified index.
|
||||
// No bounds checking is performed: the behavior is undefined if index >= number of enum values.
|
||||
template <typename E>
|
||||
|
|
|
|||
|
|
@ -176,6 +176,38 @@ TEST_CASE("enum_index") {
|
|||
REQUIRE_FALSE(enum_index(static_cast<number>(0)).has_value());
|
||||
}
|
||||
|
||||
TEST_CASE("contains_value") {
|
||||
REQUIRE(contains_value<Color>(-12));
|
||||
REQUIRE(contains_value<Color>(7));
|
||||
REQUIRE(contains_value<Color>(15));
|
||||
REQUIRE_FALSE(contains_value<Color>(42));
|
||||
REQUIRE_FALSE(contains_value<Color>(-120));
|
||||
REQUIRE_FALSE(contains_value<Color>(0));
|
||||
|
||||
constexpr auto no = enum_integer(Numbers::one);
|
||||
REQUIRE(contains_value<Numbers>(no));
|
||||
REQUIRE(contains_value<Numbers>(enum_integer(Numbers::two)));
|
||||
REQUIRE(contains_value<Numbers>(enum_integer(Numbers::three)));
|
||||
REQUIRE_FALSE(contains_value<Numbers>(enum_integer(Numbers::many)));
|
||||
|
||||
constexpr auto dr = enum_integer(Directions::Right);
|
||||
REQUIRE(contains_value<Directions&>(dr));
|
||||
REQUIRE(contains_value<Directions>(Directions::Down));
|
||||
REQUIRE(contains_value<Directions>(Directions::Up));
|
||||
REQUIRE_FALSE(contains_value<Directions>(static_cast<Directions>(0)));
|
||||
|
||||
constexpr auto nt = contains_value<number>(number::three);
|
||||
REQUIRE(contains_value<number>(number::one));
|
||||
REQUIRE(contains_value<number>(100));
|
||||
REQUIRE(contains_value<number>(200));
|
||||
REQUIRE(contains_value<number>(300));
|
||||
REQUIRE(contains_value<number>(number::two));
|
||||
REQUIRE(nt);
|
||||
REQUIRE_FALSE(contains_value<number>(number::four));
|
||||
REQUIRE_FALSE(contains_value<number>(111));
|
||||
REQUIRE_FALSE(contains_value<number>(0));
|
||||
}
|
||||
|
||||
TEST_CASE("enum_value") {
|
||||
constexpr auto cr = enum_value<Color>(0);
|
||||
REQUIRE(cr == Color::RED);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue