mirror of
https://github.com/Neargye/magic_enum.git
synced 2026-01-10 23:44:29 +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 {
|
namespace detail {
|
||||||
|
|
||||||
template <auto V, typename = std::enable_if_t<std::is_enum_v<std::decay_t<decltype(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<std::decay_t<decltype(V)>, V>;
|
using enum_constant = std::integral_constant<E, V>;
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
inline constexpr bool always_false_v = false;
|
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<>>
|
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;
|
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;
|
using enum_concept = T;
|
||||||
|
|
||||||
template <typename T, bool = std::is_enum_v<T>>
|
template <typename T, bool = std::is_enum_v<T>>
|
||||||
|
|
@ -717,6 +717,13 @@ struct underlying_type {};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct underlying_type<T, true> : std::underlying_type<std::decay_t<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>
|
template <typename Value, typename = void>
|
||||||
struct constexpr_hash_t;
|
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_FOR_EACH_256
|
||||||
#undef MAGIC_ENUM_CASE
|
#undef MAGIC_ENUM_CASE
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename E, typename Lambda, std::size_t... I>
|
template <typename E, typename Lambda, std::size_t... I>
|
||||||
constexpr auto for_each(Lambda&& lambda, std::index_sequence<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
|
} // namespace magic_enum::detail
|
||||||
|
|
||||||
// Checks is magic_enum supported compiler.
|
// Checks is magic_enum supported compiler.
|
||||||
|
|
@ -1049,10 +1064,19 @@ template <typename E>
|
||||||
if constexpr (detail::count_v<D> == 0) {
|
if constexpr (detail::count_v<D> == 0) {
|
||||||
return {}; // Empty enum.
|
return {}; // Empty enum.
|
||||||
} else if constexpr (detail::is_sparse_v<D> || detail::is_flags_v<D>) {
|
} 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>(
|
return detail::constexpr_switch<&detail::values_v<D>, detail::case_call_t::index>(
|
||||||
[](std::size_t i) { return optional<std::size_t>{i}; },
|
[](std::size_t i) { return optional<std::size_t>{i}; },
|
||||||
value,
|
value,
|
||||||
detail::default_result_type_lambda<optional<std::size_t>>);
|
detail::default_result_type_lambda<optional<std::size_t>>);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
const auto v = static_cast<U>(value);
|
const auto v = static_cast<U>(value);
|
||||||
if (v >= detail::min_v<D> && v <= detail::max_v<D>) {
|
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.
|
return {}; // Invalid value or out of range.
|
||||||
} else {
|
} 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.
|
return {}; // Empty enum.
|
||||||
} else if constexpr (detail::is_sparse_v<D>) {
|
} else if constexpr (detail::is_sparse_v<D>) {
|
||||||
if constexpr (detail::is_flags_v<D>) {
|
if constexpr (detail::is_flags_v<D>) {
|
||||||
constexpr auto count = detail::count_v<D>;
|
|
||||||
auto check_value = U{0};
|
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) {
|
if (const auto v = static_cast<U>(enum_value<D>(i)); (value & v) != 0) {
|
||||||
check_value |= v;
|
check_value |= v;
|
||||||
}
|
}
|
||||||
|
|
@ -1163,10 +1189,19 @@ template <typename E>
|
||||||
}
|
}
|
||||||
return {}; // Invalid value or out of range.
|
return {}; // Invalid value or out of range.
|
||||||
} else {
|
} 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>(
|
return detail::constexpr_switch<&detail::values_v<D>, detail::case_call_t::value>(
|
||||||
[](D v) { return optional<D>{v}; },
|
[](D v) { return optional<D>{v}; },
|
||||||
static_cast<D>(value),
|
static_cast<D>(value),
|
||||||
detail::default_result_type_lambda<optional<D>>);
|
detail::default_result_type_lambda<optional<D>>);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
constexpr auto min = detail::min_v<D>;
|
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.
|
return {}; // Invalid value or out of range.
|
||||||
} else if constexpr (detail::count_v<D> > 0) {
|
} else if constexpr (detail::count_v<D> > 0) {
|
||||||
if constexpr (detail::is_default_predicate<BinaryPredicate>()) {
|
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>(
|
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]}; },
|
[](std::size_t i) { return optional<D>{detail::values_v<D>[i]}; },
|
||||||
value,
|
value,
|
||||||
detail::default_result_type_lambda<optional<D>>,
|
detail::default_result_type_lambda<optional<D>>,
|
||||||
[&p](string_view lhs, string_view rhs) { return detail::cmp_equal(lhs, rhs, p); });
|
[&p](string_view lhs, string_view rhs) { return detail::cmp_equal(lhs, rhs, p); });
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
for (std::size_t i = 0; i < detail::count_v<D>; ++i) {
|
for (std::size_t i = 0; i < detail::count_v<D>; ++i) {
|
||||||
if (detail::cmp_equal(value, detail::names_v<D>[i], p)) {
|
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>
|
template <typename Result = void, typename E, typename Lambda>
|
||||||
constexpr auto enum_switch(Lambda&& lambda, E value) -> detail::enable_if_t<E, Result> {
|
constexpr auto enum_switch(Lambda&& lambda, E value) -> detail::enable_if_t<E, Result> {
|
||||||
using D = std::decay_t<E>;
|
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>(
|
return detail::constexpr_switch<&detail::values_v<D>, detail::case_call_t::value>(
|
||||||
std::forward<Lambda>(lambda),
|
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>
|
template <typename Result, typename E, typename Lambda>
|
||||||
constexpr auto enum_switch(Lambda&& lambda, E value, Result&& result) -> detail::enable_if_t<E, Result> {
|
constexpr auto enum_switch(Lambda&& lambda, E value, Result&& result) -> detail::enable_if_t<E, Result> {
|
||||||
using D = std::decay_t<E>;
|
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>(
|
return detail::constexpr_switch<&detail::values_v<D>, detail::case_call_t::value>(
|
||||||
std::forward<Lambda>(lambda),
|
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> {
|
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.");
|
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>;
|
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))) {
|
if (const auto v = enum_cast<D>(name, std::forward<BinaryPredicate>(p))) {
|
||||||
return enum_switch<Result, D>(std::forward<Lambda>(lambda), *v);
|
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> {
|
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.");
|
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>;
|
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))) {
|
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));
|
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>
|
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> {
|
constexpr auto enum_switch(Lambda&& lambda, underlying_type_t<E> value) -> detail::enable_if_t<E, Result> {
|
||||||
using D = std::decay_t<E>;
|
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)) {
|
if (const auto v = enum_cast<D>(value)) {
|
||||||
return enum_switch<Result, D>(std::forward<Lambda>(lambda), *v);
|
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>
|
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> {
|
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>;
|
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)) {
|
if (const auto v = enum_cast<D>(value)) {
|
||||||
return enum_switch<Result, D>(std::forward<Lambda>(lambda), *v, std::forward<Result>(result));
|
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);
|
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) {
|
constexpr auto enum_for_each(Lambda&& lambda) {
|
||||||
using D = std::decay_t<E>;
|
using D = std::decay_t<E>;
|
||||||
static_assert(std::is_enum_v<D>, "magic_enum::enum_for_each requires enum type.");
|
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 {
|
namespace ostream_operators {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue