From 612033ab5d2f5344a8c3c775ffc19ff648f1c289 Mon Sep 17 00:00:00 2001 From: neargye Date: Tue, 8 Nov 2022 20:21:00 +0400 Subject: [PATCH] add suport enum_switch without defined MAGIC_ENUM_ENABLE_HASH --- include/magic_enum.hpp | 1 + include/magic_enum_switch.hpp | 57 +++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 623591a..51c1bc8 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -732,6 +732,7 @@ template struct underlying_type : std::underlying_type> {}; #if defined(MAGIC_ENUM_ENABLE_HASH) + template inline constexpr bool has_hash = true; diff --git a/include/magic_enum_switch.hpp b/include/magic_enum_switch.hpp index dd49615..2c90190 100644 --- a/include/magic_enum_switch.hpp +++ b/include/magic_enum_switch.hpp @@ -93,6 +93,53 @@ constexpr auto result_type() noexcept { 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) + +template +inline constexpr auto default_result_type_lambda = []() noexcept(std::is_nothrow_default_constructible_v) { return T{}; }; + +template <> +inline constexpr auto default_result_type_lambda = []() noexcept {}; + +template +constexpr R invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r_v) { + if constexpr (std::is_void_v) { + std::forward(f)(std::forward(args)...); + } else { + return static_cast(std::forward(f)(std::forward(args)...)); + } +} + +template +constexpr decltype(auto) constexpr_switch_impl(F&& f, E value, Def&& def) { + if constexpr(I < End) { + constexpr auto v = enum_constant()>{}; + if (value == v) { + if constexpr (std::is_invocable_r_v) { + return invoke_r(std::forward(f), v); + } else { + return def(); + } + } else { + return constexpr_switch_impl(std::forward(f), value, std::forward(def)); + } + } else { + return def(); + } +} + +template +constexpr decltype(auto) constexpr_switch(F&& f, E value, Def&& def) { + static_assert(is_enum_v, "magic_enum::detail::constexpr_switch_impl requires enum type."); + + if constexpr (count_v == 0) { + return def(); + } else { + return constexpr_switch_impl<0, count_v, R>(std::forward(f), value, std::forward(def)); + } +} +#endif + } // namespace magic_enum::detail template > @@ -106,7 +153,10 @@ constexpr decltype(auto) enum_switch(F&& f, E value) { value, detail::default_result_type_lambda); #else - static_assert(detail::has_hash, "magic_enum::enum_switch requires defined MAGIC_ENUM_ENABLE_HASH"); + return detail::constexpr_switch( + std::forward(f), + value, + detail::default_result_type_lambda); #endif } @@ -121,7 +171,10 @@ constexpr decltype(auto) enum_switch(F&& f, E value, Result&& result) { value, [&result]() -> R { return std::forward(result); }); #else - static_assert(detail::has_hash, "magic_enum::enum_switch requires defined MAGIC_ENUM_ENABLE_HASH"); + return detail::constexpr_switch( + std::forward(f), + value, + [&result]() -> R { return std::forward(result); }); #endif }