1
0
Fork 0
mirror of https://github.com/Neargye/magic_enum.git synced 2026-01-09 23:34:23 +00:00
This commit is contained in:
neargye 2022-02-10 20:17:44 +02:00
parent 1f8e29b140
commit 63ff515163
4 changed files with 43 additions and 41 deletions

View file

@ -324,6 +324,15 @@ constexpr I log2(I value) noexcept {
return ret;
}
constexpr std::size_t cantor_pair(size_t v1, size_t v2) noexcept {
return (((v1 + v2) * (v1 + v2 + 1)) >> 1) + v2;
}
template <typename... Ts>
constexpr std::size_t cantor_pair(std::size_t v1, std::size_t head, Ts... tail) noexcept {
return cantor_pair(cantor_pair(v1, head), tail...);
}
template <typename T>
inline constexpr bool is_enum_v = std::is_enum_v<T> && std::is_same_v<T, std::decay_t<T>>;
@ -609,15 +618,6 @@ struct underlying_type {};
template <typename T>
struct underlying_type<T, true> : std::underlying_type<std::decay_t<T>> {};
constexpr size_t cantor_pair(size_t v1, size_t v2) noexcept {
return (((v1 + v2) * (v1 + v2 + 1)) >> 1) + v2;
}
template<typename ... Ts>
constexpr size_t cantor_pair(size_t v1, size_t head, Ts ... tail) noexcept {
return cantor_pair(cantor_pair(v1, head), tail...);
}
} // namespace magic_enum::detail
// Checks is magic_enum supported compiler.
@ -887,11 +887,17 @@ template <typename E>
return {}; // Invalid value or out of range.
}
template<typename ... Es>
[[nodiscard]] constexpr size_t enum_fuse(Es ... enums) {
// Returns a bijective mix of several enum values with [Cantor pairing function](https://en.wikipedia.org/wiki/Pairing_function). This can be used to emulate 2D switch/case statements.
template <typename... Es>
[[nodiscard]] constexpr auto enum_fuse(Es... values) -> std::enable_if_t<(std::is_enum_v<std::decay_t<Es>> && ...), std::size_t>{
static_assert(sizeof...(Es) >= 2, "magic_enum::enum_fuse requires at least 2 enums");
#ifdef __cpp_lib_is_constant_evaluated
if (std::is_constant_evaluated() && !(enum_index(values).has_value() && ...)) {
throw std::logic_error("magic_enum::enum_fuse accepts only in-range enum values");
}
#endif
// Add 1 to prevent matching 2D fusions with 3D fusions etc.
return detail::cantor_pair((enum_index(enums).value() + 1)...);
return assert((enum_index(values).has_value() && ...)), detail::cantor_pair((enum_index(values).value() + 1)...);
}
// Checks whether enum contains enumerator with such enum value.