32 #ifndef NEARGYE_MAGIC_ENUM_SWITCH_HPP
33 #define NEARGYE_MAGIC_ENUM_SWITCH_HPP
50 template <
typename F,
typename V,
bool = std::is_invocable_v<F, V>>
53 template <
typename F,
typename V>
56 template <
typename F,
typename V>
59 template <
typename E,
enum_subtype S,
typename F, std::size_t... I>
61 static_assert(std::is_enum_v<E>,
"magic_enum::detail::invocable_index requires enum type.");
63 if constexpr (count_v<E, S> == 0) {
66 return std::common_type<invoke_result_t<F, enum_constant<values_v<E, S>[I]>>...>{};
70 template <
typename E, enum_subtype S,
typename Result,
typename F>
72 static_assert(std::is_enum_v<E>,
"magic_enum::detail::result_type requires enum type.");
74 constexpr
auto seq = std::make_index_sequence<count_v<E, S>>{};
75 using R =
typename decltype(common_invocable<E, S, F>(seq))::type;
76 if constexpr (std::is_same_v<Result, default_result_type>) {
77 if constexpr (std::is_same_v<R, nonesuch>) {
83 if constexpr (std::is_convertible_v<R, Result>) {
85 }
else if constexpr (std::is_convertible_v<Result, R>) {
93 template <
typename E, enum_subtype S,
typename Result,
typename F,
typename D = std::decay_t<E>,
typename R =
typename decltype(result_type<D, S, Result, F>())::type>
94 using result_t = std::enable_if_t<std::is_enum_v<D> && !std::is_same_v<R, nonesuch>, R>;
96 #if !defined(MAGIC_ENUM_ENABLE_HASH) && !defined(MAGIC_ENUM_ENABLE_HASH_SWITCH)
98 template <
typename T =
void>
104 template <std::
size_t I, std::
size_t End,
typename R,
typename E, enum_subtype S,
typename F,
typename Def>
106 if constexpr(I < End) {
109 if constexpr (std::is_invocable_r_v<R, F, decltype(v)>) {
110 return static_cast<R
>(std::forward<F>(f)(v));
115 return constexpr_switch_impl<I + 1, End, R, E, S>(std::forward<F>(f),
value, std::forward<Def>(def));
122 template <
typename R,
typename E, enum_subtype S,
typename F,
typename Def>
124 static_assert(is_enum_v<E>,
"magic_enum::detail::constexpr_switch requires enum type.");
126 if constexpr (count_v<E, S> == 0) {
129 return constexpr_switch_impl<0, count_v<E, S>, R, E, S>(std::forward<F>(f),
value, std::forward<Def>(def));
136 template <
typename Result = detail::default_result_type,
typename E, detail::enum_subtype S = detail::subtype_v<E>,
typename F,
typename R = detail::result_t<E, S, Result, F>>
138 using D = std::decay_t<E>;
139 static_assert(std::is_enum_v<D>,
"magic_enum::enum_switch requires enum type.");
140 static_assert(detail::is_reflected_v<D, S>,
"magic_enum requires enum implementation and valid max and min.");
142 #if defined(MAGIC_ENUM_ENABLE_HASH) || defined(MAGIC_ENUM_ENABLE_HASH_SWITCH)
146 detail::default_result_type_lambda<R>);
148 return detail::constexpr_switch<R, D, S>(
151 detail::default_result_type_lambda<R>);
155 template <
typename Result = detail::default_result_type, detail::enum_subtype S,
typename E,
typename F,
typename R = detail::result_t<E, S, Result, F>>
157 return enum_switch<Result, E, S>(std::forward<F>(f),
value);
160 template <
typename Result,
typename E, detail::enum_subtype S = detail::subtype_v<E>,
typename F,
typename R = detail::result_t<E, S, Result, F>>
162 using D = std::decay_t<E>;
163 static_assert(std::is_enum_v<D>,
"magic_enum::enum_switch requires enum type.");
164 static_assert(detail::is_reflected_v<D, S>,
"magic_enum requires enum implementation and valid max and min.");
166 #if defined(MAGIC_ENUM_ENABLE_HASH) || defined(MAGIC_ENUM_ENABLE_HASH_SWITCH)
170 [&result]() -> R {
return std::forward<Result>(result); });
172 return detail::constexpr_switch<R, D, S>(
175 [&result]() -> R {
return std::forward<Result>(result); });
179 template <
typename Result, detail::enum_subtype S,
typename E,
typename F,
typename R = detail::result_t<E, S, Result, F>>
181 return enum_switch<Result, E, S>(std::forward<F>(f),
value, std::forward<Result>(result));
189 template <
typename T>
192 template <
typename T>
195 #endif // NEARGYE_MAGIC_ENUM_SWITCH_HPP