mirror of
https://github.com/Neargye/magic_enum.git
synced 2026-01-09 23:34:23 +00:00
No hash (#208)
This commit is contained in:
parent
8f9f4afee7
commit
d26a7a2293
1 changed files with 63 additions and 8 deletions
|
|
@ -166,8 +166,8 @@ constexpr customize_t enum_type_name() noexcept {
|
|||
|
||||
namespace detail {
|
||||
|
||||
template <auto V, typename = std::enable_if_t<std::is_enum_v<std::decay_t<decltype(V)>>>>
|
||||
using enum_constant = std::integral_constant<std::decay_t<decltype(V)>, V>;
|
||||
template <auto V, typename E = std::decay_t<decltype(V)>, std::enable_if_t<std::is_enum_v<E>, int> = 0>
|
||||
using enum_constant = std::integral_constant<E, V>;
|
||||
|
||||
template <typename... T>
|
||||
inline constexpr bool always_false_v = false;
|
||||
|
|
@ -696,7 +696,7 @@ struct enable_if_enum<true, R> {
|
|||
template <typename T, typename R, typename BinaryPredicate = std::equal_to<>>
|
||||
using enable_if_t = typename enable_if_enum<std::is_enum_v<std::decay_t<T>> && std::is_invocable_r_v<bool, BinaryPredicate, char, char>, R>::type;
|
||||
|
||||
template <typename T, typename Enable = std::enable_if_t<std::is_enum_v<std::decay_t<T>>>>
|
||||
template <typename T, std::enable_if_t<std::is_enum_v<std::decay_t<T>>, int> = 0>
|
||||
using enum_concept = T;
|
||||
|
||||
template <typename T, bool = std::is_enum_v<T>>
|
||||
|
|
@ -717,6 +717,13 @@ struct underlying_type {};
|
|||
template <typename T>
|
||||
struct underlying_type<T, true> : std::underlying_type<std::decay_t<T>> {};
|
||||
|
||||
#if defined(MAGIC_ENUM_NO_HASH)
|
||||
template <typename T>
|
||||
inline constexpr bool has_hash = false;
|
||||
#else
|
||||
template <typename T>
|
||||
inline constexpr bool has_hash = true;
|
||||
|
||||
template <typename Value, typename = void>
|
||||
struct constexpr_hash_t;
|
||||
|
||||
|
|
@ -930,6 +937,7 @@ constexpr std::invoke_result_t<ResultGetterType> constexpr_switch(
|
|||
|
||||
#undef MAGIC_ENUM_FOR_EACH_256
|
||||
#undef MAGIC_ENUM_CASE
|
||||
#endif
|
||||
|
||||
template <typename E, typename Lambda, std::size_t... I>
|
||||
constexpr auto for_each(Lambda&& lambda, std::index_sequence<I...>) {
|
||||
|
|
@ -946,6 +954,13 @@ constexpr auto for_each(Lambda&& lambda, std::index_sequence<I...>) {
|
|||
}
|
||||
}
|
||||
|
||||
template <typename E, typename Lambda, std::size_t... I>
|
||||
constexpr bool all_invocable(std::index_sequence<I...>) {
|
||||
static_assert(is_enum_v<E>, "magic_enum::detail::all_invocable requires enum type.");
|
||||
|
||||
return (std::is_invocable_v<Lambda, enum_constant<values_v<E>[I]>> && ...);
|
||||
}
|
||||
|
||||
} // namespace magic_enum::detail
|
||||
|
||||
// Checks is magic_enum supported compiler.
|
||||
|
|
@ -1049,10 +1064,19 @@ template <typename E>
|
|||
if constexpr (detail::count_v<D> == 0) {
|
||||
return {}; // Empty enum.
|
||||
} else if constexpr (detail::is_sparse_v<D> || detail::is_flags_v<D>) {
|
||||
#if defined(MAGIC_ENUM_NO_HASH)
|
||||
for (std::size_t i = 0; i < detail::count_v<D>; ++i) {
|
||||
if (enum_value<D>(i) == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return {}; // Invalid value or out of range.
|
||||
#else
|
||||
return detail::constexpr_switch<&detail::values_v<D>, detail::case_call_t::index>(
|
||||
[](std::size_t i) { return optional<std::size_t>{i}; },
|
||||
value,
|
||||
detail::default_result_type_lambda<optional<std::size_t>>);
|
||||
#endif
|
||||
} else {
|
||||
const auto v = static_cast<U>(value);
|
||||
if (v >= detail::min_v<D> && v <= detail::max_v<D>) {
|
||||
|
|
@ -1120,7 +1144,10 @@ template <typename E>
|
|||
|
||||
return {}; // Invalid value or out of range.
|
||||
} else {
|
||||
return string{enum_name<D>(value)};
|
||||
if (const auto name = enum_name<D>(value); !name.empty()) {
|
||||
return {name.data(), name.size()};
|
||||
}
|
||||
return {}; // Invalid value or out of range.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1150,9 +1177,8 @@ template <typename E>
|
|||
return {}; // Empty enum.
|
||||
} else if constexpr (detail::is_sparse_v<D>) {
|
||||
if constexpr (detail::is_flags_v<D>) {
|
||||
constexpr auto count = detail::count_v<D>;
|
||||
auto check_value = U{0};
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
for (std::size_t i = 0; i < detail::count_v<D>; ++i) {
|
||||
if (const auto v = static_cast<U>(enum_value<D>(i)); (value & v) != 0) {
|
||||
check_value |= v;
|
||||
}
|
||||
|
|
@ -1163,10 +1189,19 @@ template <typename E>
|
|||
}
|
||||
return {}; // Invalid value or out of range.
|
||||
} else {
|
||||
#if defined(MAGIC_ENUM_NO_HASH)
|
||||
for (std::size_t i = 0; i < detail::count_v<D>; ++i) {
|
||||
if (value == static_cast<U>(enum_value<D>(i))) {
|
||||
return static_cast<D>(value);
|
||||
}
|
||||
}
|
||||
return {}; // Invalid value or out of range.
|
||||
#else
|
||||
return detail::constexpr_switch<&detail::values_v<D>, detail::case_call_t::value>(
|
||||
[](D v) { return optional<D>{v}; },
|
||||
static_cast<D>(value),
|
||||
detail::default_result_type_lambda<optional<D>>);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
constexpr auto min = detail::min_v<D>;
|
||||
|
|
@ -1214,11 +1249,20 @@ template <typename E, typename BinaryPredicate = std::equal_to<>>
|
|||
return {}; // Invalid value or out of range.
|
||||
} else if constexpr (detail::count_v<D> > 0) {
|
||||
if constexpr (detail::is_default_predicate<BinaryPredicate>()) {
|
||||
#if defined(MAGIC_ENUM_NO_HASH)
|
||||
for (std::size_t i = 0; i < detail::count_v<D>; ++i) {
|
||||
if (detail::cmp_equal(value, detail::names_v<D>[i], p)) {
|
||||
return enum_value<D>(i);
|
||||
}
|
||||
}
|
||||
return {}; // Invalid value or out of range.
|
||||
#else
|
||||
return detail::constexpr_switch<&detail::names_v<D>, detail::case_call_t::index>(
|
||||
[](std::size_t i) { return optional<D>{detail::values_v<D>[i]}; },
|
||||
value,
|
||||
detail::default_result_type_lambda<optional<D>>,
|
||||
[&p](string_view lhs, string_view rhs) { return detail::cmp_equal(lhs, rhs, p); });
|
||||
#endif
|
||||
} else {
|
||||
for (std::size_t i = 0; i < detail::count_v<D>; ++i) {
|
||||
if (detail::cmp_equal(value, detail::names_v<D>[i], p)) {
|
||||
|
|
@ -1259,6 +1303,7 @@ template <typename E, typename BinaryPredicate = std::equal_to<>>
|
|||
template <typename Result = void, typename E, typename Lambda>
|
||||
constexpr auto enum_switch(Lambda&& lambda, E value) -> detail::enable_if_t<E, Result> {
|
||||
using D = std::decay_t<E>;
|
||||
static_assert(detail::has_hash<D>, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH");
|
||||
|
||||
return detail::constexpr_switch<&detail::values_v<D>, detail::case_call_t::value>(
|
||||
std::forward<Lambda>(lambda),
|
||||
|
|
@ -1269,6 +1314,7 @@ constexpr auto enum_switch(Lambda&& lambda, E value) -> detail::enable_if_t<E, R
|
|||
template <typename Result, typename E, typename Lambda>
|
||||
constexpr auto enum_switch(Lambda&& lambda, E value, Result&& result) -> detail::enable_if_t<E, Result> {
|
||||
using D = std::decay_t<E>;
|
||||
static_assert(detail::has_hash<D>, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH");
|
||||
|
||||
return detail::constexpr_switch<&detail::values_v<D>, detail::case_call_t::value>(
|
||||
std::forward<Lambda>(lambda),
|
||||
|
|
@ -1280,6 +1326,7 @@ template <typename E, typename Result = void, typename BinaryPredicate = std::eq
|
|||
constexpr auto enum_switch(Lambda&& lambda, string_view name, BinaryPredicate&& p = {}) -> detail::enable_if_t<E, Result, BinaryPredicate> {
|
||||
static_assert(std::is_invocable_r_v<bool, BinaryPredicate, char, char>, "magic_enum::enum_switch requires bool(char, char) invocable predicate.");
|
||||
using D = std::decay_t<E>;
|
||||
static_assert(detail::has_hash<D>, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH");
|
||||
|
||||
if (const auto v = enum_cast<D>(name, std::forward<BinaryPredicate>(p))) {
|
||||
return enum_switch<Result, D>(std::forward<Lambda>(lambda), *v);
|
||||
|
|
@ -1291,6 +1338,7 @@ template <typename E, typename Result, typename BinaryPredicate = std::equal_to<
|
|||
constexpr auto enum_switch(Lambda&& lambda, string_view name, Result&& result, BinaryPredicate&& p = {}) -> detail::enable_if_t<E, Result, BinaryPredicate> {
|
||||
static_assert(std::is_invocable_r_v<bool, BinaryPredicate, char, char>, "magic_enum::enum_switch requires bool(char, char) invocable predicate.");
|
||||
using D = std::decay_t<E>;
|
||||
static_assert(detail::has_hash<D>, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH");
|
||||
|
||||
if (const auto v = enum_cast<D>(name, std::forward<BinaryPredicate>(p))) {
|
||||
return enum_switch<Result, D>(std::forward<Lambda>(lambda), *v, std::forward<Result>(result));
|
||||
|
|
@ -1301,6 +1349,7 @@ constexpr auto enum_switch(Lambda&& lambda, string_view name, Result&& result, B
|
|||
template <typename E, typename Result = void, typename Lambda>
|
||||
constexpr auto enum_switch(Lambda&& lambda, underlying_type_t<E> value) -> detail::enable_if_t<E, Result> {
|
||||
using D = std::decay_t<E>;
|
||||
static_assert(detail::has_hash<D>, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH");
|
||||
|
||||
if (const auto v = enum_cast<D>(value)) {
|
||||
return enum_switch<Result, D>(std::forward<Lambda>(lambda), *v);
|
||||
|
|
@ -1311,6 +1360,7 @@ constexpr auto enum_switch(Lambda&& lambda, underlying_type_t<E> value) -> detai
|
|||
template <typename E, typename Result, typename Lambda>
|
||||
constexpr auto enum_switch(Lambda&& lambda, underlying_type_t<E> value, Result&& result) -> detail::enable_if_t<E, Result> {
|
||||
using D = std::decay_t<E>;
|
||||
static_assert(detail::has_hash<D>, "magic_enum::enum_switch requires no defined MAGIC_ENUM_NO_HASH");
|
||||
|
||||
if (const auto v = enum_cast<D>(value)) {
|
||||
return enum_switch<Result, D>(std::forward<Lambda>(lambda), *v, std::forward<Result>(result));
|
||||
|
|
@ -1318,12 +1368,17 @@ constexpr auto enum_switch(Lambda&& lambda, underlying_type_t<E> value, Result&&
|
|||
return std::forward<Result>(result);
|
||||
}
|
||||
|
||||
template <typename E, typename Lambda>
|
||||
template <typename E, typename Lambda, detail::enable_if_t<E, int> = 0>
|
||||
constexpr auto enum_for_each(Lambda&& lambda) {
|
||||
using D = std::decay_t<E>;
|
||||
static_assert(std::is_enum_v<D>, "magic_enum::enum_for_each requires enum type.");
|
||||
constexpr auto sep = std::make_index_sequence<detail::count_v<D>>{};
|
||||
|
||||
return detail::for_each<D>(std::forward<Lambda>(lambda), std::make_index_sequence<detail::count_v<D>>{});
|
||||
if constexpr (detail::all_invocable<D, Lambda>(sep)) {
|
||||
return detail::for_each<D>(std::forward<Lambda>(lambda), sep);
|
||||
} else {
|
||||
static_assert(detail::always_false_v<D>, "magic_enum::enum_for_each requires invocable of all enum value.");
|
||||
}
|
||||
}
|
||||
|
||||
namespace ostream_operators {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue