32 #ifndef NEARGYE_MAGIC_ENUM_FLAGS_HPP
33 #define NEARGYE_MAGIC_ENUM_FLAGS_HPP
37 #if defined(__clang__)
38 # pragma clang diagnostic push
39 #elif defined(__GNUC__)
40 # pragma GCC diagnostic push
41 # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // May be used uninitialized 'return {};'.
42 #elif defined(_MSC_VER)
43 # pragma warning(push)
50 template <
typename E, enum_subtype S,
typename U = std::underlying_type_t<E>>
52 static_assert(S ==
enum_subtype::flags,
"magic_enum::detail::values_ors requires valid subtype.");
55 for (std::size_t i = 0; i < count_v<E, S>; ++i) {
56 ors |=
static_cast<U
>(values_v<E, S>[i]);
68 using D = std::decay_t<E>;
71 static_assert(detail::is_reflected_v<D, S>,
"magic_enum requires enum implementation and valid max and min.");
74 auto check_value = U{0};
75 for (std::size_t i = 0; i < detail::count_v<D, S>; ++i) {
76 if (
const auto v =
static_cast<U
>(enum_value<D, S>(i)); (
static_cast<U
>(
value) & v) != 0) {
77 if (
const auto n = detail::names_v<D, S>[i]; !
n.empty()) {
82 name.append(
n.data(),
n.size());
89 if (check_value != 0 && check_value ==
static_cast<U
>(
value)) {
99 using D = std::decay_t<E>;
102 static_assert(detail::is_reflected_v<D, S>,
"magic_enum requires enum implementation and valid max and min.");
104 if constexpr (detail::count_v<D, S> == 0) {
105 static_cast<void>(
value);
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) {
116 if (check_value != 0 && check_value ==
value) {
117 return static_cast<D
>(
value);
120 constexpr
auto min = detail::min_v<D, S>;
121 constexpr
auto max = detail::values_ors<D, S>();
124 return static_cast<D
>(
value);
133 template <
typename E,
typename BinaryPredicate = std::equal_to<>>
134 [[nodiscard]] constexpr
auto enum_flags_cast(string_view
value, [[maybe_unused]] BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable<BinaryPredicate>()) -> detail::enable_if_t<E, optional<std::decay_t<E>>, BinaryPredicate> {
135 using D = std::decay_t<E>;
136 using U = underlying_type_t<D>;
138 static_assert(detail::is_reflected_v<D, S>,
"magic_enum requires enum implementation and valid max and min.");
140 if constexpr (detail::count_v<D, S> == 0) {
141 static_cast<void>(
value);
145 while (!
value.empty()) {
147 const auto s = (d == string_view::npos) ?
value :
value.substr(0, d);
149 for (std::size_t i = 0; i < detail::count_v<D, S>; ++i) {
151 f =
static_cast<U
>(enum_value<D, S>(i));
159 value.remove_prefix((d == string_view::npos) ?
value.size() : d + 1);
162 if (result != U{0}) {
163 return static_cast<D
>(result);
170 template <
typename E>
172 using D = std::decay_t<E>;
175 return static_cast<bool>(enum_flags_cast<D>(
static_cast<U
>(
value)));
179 template <
typename E>
181 using D = std::decay_t<E>;
183 return static_cast<bool>(enum_flags_cast<D>(
value));
187 template <
typename E,
typename BinaryPredicate = std::equal_to<>>
188 [[nodiscard]] constexpr
auto enum_flags_contains(string_view
value, BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable<BinaryPredicate>()) -> detail::enable_if_t<E, bool, BinaryPredicate> {
189 using D = std::decay_t<E>;
191 return static_cast<bool>(enum_flags_cast<D>(
value, std::move(p)));
196 template <
typename E>
200 return static_cast<U
>(flag) && ((
static_cast<U
>(flags) &
static_cast<U
>(flag)) ==
static_cast<U
>(flag));
205 template <
typename E>
209 return (
static_cast<U
>(lhs) &
static_cast<U
>(rhs)) != 0;
214 #if defined(__clang__)
215 # pragma clang diagnostic pop
216 #elif defined(__GNUC__)
217 # pragma GCC diagnostic pop
218 #elif defined(_MSC_VER)
219 # pragma warning(pop)
222 #endif // NEARGYE_MAGIC_ENUM_FLAGS_HPP