| 96 | // Returns optional with enum-flags value. |
| 97 | template <typename E> |
| 98 | [[nodiscard]] constexpr auto enum_flags_cast(underlying_type_t<E> value) noexcept -> detail::enable_if_t<E, optional<std::decay_t<E>>> { |
| 99 | using D = std::decay_t<E>; |
| 100 | using U = underlying_type_t<D>; |
| 101 | constexpr auto S = detail::enum_subtype::flags; |
| 102 | static_assert(detail::is_reflected_v<D, S>, "magic_enum requires enum implementation and valid max and min."); |
| 103 | |
| 104 | if constexpr (detail::count_v<D, S> == 0) { |
| 105 | static_cast<void>(value); |
| 106 | return {}; // Empty enum. |
| 107 | } else { |
| 108 | if constexpr (detail::is_sparse_v<D, S>) { |
| 109 | auto check_value = U{0}; |
| 110 | for (std::size_t i = 0; i < detail::count_v<D, S>; ++i) { |
| 111 | if (const auto v = static_cast<U>(enum_value<D, S>(i)); (value & v) != 0) { |
| 112 | check_value |= v; |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | if (check_value != 0 && check_value == value) { |
| 117 | return static_cast<D>(value); |
| 118 | } |
| 119 | } else { |
| 120 | constexpr auto min = detail::min_v<D, S>; |
| 121 | constexpr auto max = detail::values_ors<D, S>(); |
| 122 | |
| 123 | if (value >= min && value <= max) { |
| 124 | return static_cast<D>(value); |
| 125 | } |
| 126 | } |
| 127 | return {}; // Invalid value or out of range. |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | // Returns enum-flags value from name. |
| 132 | // Returns optional with enum-flags value. |