diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index cab56b6..3a8c6e1 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -1358,19 +1358,6 @@ template , typename Bi return static_cast(enum_cast(value, std::move(p))); } -template , typename F, detail::enable_if_t = 0> -constexpr auto enum_for_each(F&& f) { - using D = std::decay_t; - static_assert(std::is_enum_v, "magic_enum::enum_for_each requires enum type."); - constexpr auto sep = std::make_index_sequence>{}; - - if constexpr (detail::all_invocable(sep)) { - return detail::for_each(std::forward(f), sep); - } else { - static_assert(detail::always_false_v, "magic_enum::enum_for_each requires invocable of all enum value."); - } -} - template inline constexpr auto as_flags = AsFlags ? detail::enum_subtype::flags : detail::enum_subtype::common; diff --git a/include/magic_enum_utility.hpp b/include/magic_enum_utility.hpp index 6426494..141f348 100644 --- a/include/magic_enum_utility.hpp +++ b/include/magic_enum_utility.hpp @@ -36,6 +36,46 @@ namespace magic_enum { +namespace detail { + +template +constexpr auto for_each(F&& f, std::index_sequence) { + constexpr bool has_void_return = (std::is_void_v[I]>>> || ...); + constexpr bool all_same_return = (std::is_same_v[0]>>, std::invoke_result_t[I]>>> && ...); + + if constexpr (has_void_return) { + (f(enum_constant[I]>{}), ...); + } else if constexpr (all_same_return) { + return std::array{f(enum_constant[I]>{})...}; + } else { + return std::tuple{f(enum_constant[I]>{})...}; + } +} + +template +constexpr bool all_invocable(std::index_sequence) { + if constexpr (count_v == 0) { + return false; + } else { + return (std::is_invocable_v[I]>> && ...); + } +} + +} // namespace magic_enum::detail + +template , typename F, detail::enable_if_t = 0> +constexpr auto enum_for_each(F&& f) { + using D = std::decay_t; + static_assert(std::is_enum_v, "magic_enum::enum_for_each requires enum type."); + constexpr auto sep = std::make_index_sequence>{}; + + if constexpr (detail::all_invocable(sep)) { + return detail::for_each(std::forward(f), sep); + } else { + static_assert(detail::always_false_v, "magic_enum::enum_for_each requires invocable of all enum value."); + } +} + template > [[nodiscard]] constexpr auto enum_next_value(E value, std::ptrdiff_t n = 1) noexcept -> detail::enable_if_t>> { using D = std::decay_t;