diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 166c5b4..90d4c14 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -425,7 +425,7 @@ constexpr auto type_name() noexcept { constexpr auto name = n(); return static_string{name}; } else { - static_assert(detail::always_false_v, "magic_enum::customize invalid."); + static_assert(always_false_v, "magic_enum::customize invalid."); } } @@ -499,7 +499,7 @@ constexpr auto enum_name() noexcept { constexpr auto name = n(); return static_string{name}; } else { - static_assert(detail::always_false_v, "magic_enum::customize invalid."); + static_assert(always_false_v, "magic_enum::customize invalid."); } } diff --git a/include/magic_enum_format.hpp b/include/magic_enum_format.hpp index 046d777..3973ed0 100644 --- a/include/magic_enum_format.hpp +++ b/include/magic_enum_format.hpp @@ -58,7 +58,7 @@ struct std::formatter> && mag using D = std::decay_t; if constexpr (magic_enum::detail::supported::value) { - if constexpr (detail::subtype_v == detail::enum_subtype::flags) { + if constexpr (magic_enum::detail::subtype_v == magic_enum::detail::enum_subtype::flags) { if (const auto name = magic_enum::enum_flags_name(e); !name.empty()) { return formatter::format(std::string_view{name.data(), name.size()}, ctx); } @@ -85,7 +85,7 @@ struct fmt::formatter> && mag using D = std::decay_t; if constexpr (magic_enum::detail::supported::value) { - if constexpr (detail::subtype_v == detail::enum_subtype::flags) { + if constexpr (magic_enum::detail::subtype_v == magic_enum::detail::enum_subtype::flags) { if (const auto name = magic_enum::enum_flags_name(e); !name.empty()) { return formatter::format(std::string_view{name.data(), name.size()}, ctx); } diff --git a/include/magic_enum_fuse.hpp b/include/magic_enum_fuse.hpp index 40675c8..ef8dda3 100644 --- a/include/magic_enum_fuse.hpp +++ b/include/magic_enum_fuse.hpp @@ -38,30 +38,33 @@ namespace magic_enum { namespace detail { -template +template +inline constexpr auto subtypes_v = subtype_v>; + +template constexpr optional fuse_one_enum(optional hash, E value) noexcept { if (hash) { if (const auto index = enum_index(value)) { - return (*hash << log2(enum_count() + 1)) | *index; + return (*hash << log2(enum_count() + 1)) | *index; } } return {}; } -template +template constexpr optional fuse_enum(E value) noexcept { - return fuse_one_enum(0, value); + return fuse_one_enum(0, value); } -template +template constexpr optional fuse_enum(E head, Es... tail) noexcept { - return fuse_one_enum(fuse_enum(tail...), head); + return fuse_one_enum(fuse_enum(tail...), head); } -template +template constexpr auto typesafe_fuse_enum(Es... values) noexcept { enum class enum_fuse_t : std::uintmax_t; - const auto fuse = fuse_enum(values...); + const auto fuse = fuse_enum(values...); if (fuse) { return optional{static_cast(*fuse)}; } @@ -71,19 +74,25 @@ constexpr auto typesafe_fuse_enum(Es... values) noexcept { } // namespace magic_enum::detail // Returns a bijective mix of several enum values. This can be used to emulate 2D switch/case statements. -template +template [[nodiscard]] constexpr auto enum_fuse(Es... values) noexcept { static_assert((std::is_enum_v> && ...), "magic_enum::enum_fuse requires enum type."); static_assert(sizeof...(Es) >= 2, "magic_enum::enum_fuse requires at least 2 values."); - static_assert((detail::log2(enum_count>() + 1) + ...) <= (sizeof(std::uintmax_t) * 8), "magic_enum::enum_fuse does not work for large enums"); + static_assert((detail::log2(enum_count, S>() + 1) + ...) <= (sizeof(std::uintmax_t) * 8), "magic_enum::enum_fuse does not work for large enums"); #if defined(MAGIC_ENUM_NO_TYPESAFE_ENUM_FUSE) - const auto fuse = detail::fuse_enum...>(values...); + const auto fuse = detail::fuse_enum...>(values...); #else - const auto fuse = detail::typesafe_fuse_enum...>(values...); + const auto fuse = detail::typesafe_fuse_enum...>(values...); #endif return assert(fuse), fuse; } +// Returns a bijective mix of several enum values. This can be used to emulate 2D switch/case statements. +template +[[nodiscard]] constexpr auto enum_fuse(Es... values) noexcept { + return enum_fuse>(values...); +} + } // namespace magic_enum #endif // NEARGYE_MAGIC_ENUM_FUSE_HPP diff --git a/include/magic_enum_switch.hpp b/include/magic_enum_switch.hpp index a352811..7520d96 100644 --- a/include/magic_enum_switch.hpp +++ b/include/magic_enum_switch.hpp @@ -56,7 +56,7 @@ struct invoke_result : std::invoke_result {}; template using invoke_result_t = typename invoke_result::type; -template +template constexpr auto common_invocable(std::index_sequence) noexcept { static_assert(is_enum_v, "magic_enum::detail::invocable_index requires enum type."); @@ -67,11 +67,11 @@ constexpr auto common_invocable(std::index_sequence) noexcept { } } -template +template constexpr auto result_type() noexcept { static_assert(is_enum_v, "magic_enum::detail::result_type requires enum type."); - constexpr auto seq = std::make_index_sequence>{}; + constexpr auto seq = std::make_index_sequence>{}; using R = typename decltype(common_invocable(seq))::type; if constexpr (std::is_same_v) { if constexpr (std::is_same_v) { @@ -90,7 +90,7 @@ constexpr auto result_type() noexcept { } } -template , typename R = typename decltype(result_type())::type> +template , typename R = typename decltype(result_type())::type> using result_t = std::enable_if_t && !std::is_same_v, R>; #if !defined(MAGIC_ENUM_ENABLE_HASH) @@ -110,7 +110,7 @@ constexpr R invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r } } -template +template constexpr decltype(auto) constexpr_switch_impl(F&& f, E value, Def&& def) { if constexpr(I < End) { constexpr auto v = enum_constant()>{}; @@ -128,7 +128,7 @@ constexpr decltype(auto) constexpr_switch_impl(F&& f, E value, Def&& def) { } } -template +template constexpr decltype(auto) constexpr_switch(F&& f, E value, Def&& def) { static_assert(is_enum_v, "magic_enum::detail::constexpr_switch requires enum type.");