From 0c0b03131a82abc5e028dc2ac9c1ae3a17c6052f Mon Sep 17 00:00:00 2001 From: neargye Date: Sat, 15 Aug 2020 18:09:27 +0500 Subject: [PATCH] wip --- include/magic_enum.hpp | 114 ++++++++++++++++++++++++++++------------- 1 file changed, 77 insertions(+), 37 deletions(-) diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 6fb6d12..444c215 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -158,20 +158,31 @@ constexpr std::string_view pretty_name(std::string_view name) noexcept { return {}; // Invalid name. } +struct char_equal_to { + constexpr bool operator()(char lhs, char rhs) const noexcept { + return lhs == rhs; + } +}; + template constexpr bool cmp_equal(std::string_view lhs, std::string_view rhs, BinaryPredicate&& p) noexcept(std::is_nothrow_invocable_r_v) { - if (lhs.size() != rhs.size()) { - return false; - } - - const auto size = lhs.size(); - for (std::size_t i = 0; i < size; ++i) { - if (!p(lhs[i], rhs[i])) { + if constexpr (std::is_same_v) { + static_cast(p); + return lhs == rhs; + } else { + if (lhs.size() != rhs.size()) { return false; } - } - return true; + const auto size = lhs.size(); + for (std::size_t i = 0; i < size; ++i) { + if (!p(lhs[i], rhs[i])) { + return false; + } + } + + return true; + } } template @@ -620,7 +631,7 @@ template return detail::names_v[i]; } - return {}; // Value out of range. + return {}; // Invalid value or out of range. } // Returns std::array with string names, sorted by enum value. @@ -661,13 +672,7 @@ template [[nodiscard]] constexpr auto enum_cast(std::string_view value) noexcept -> detail::enable_if_enum_t>> { using D = std::decay_t; - for (std::size_t i = 0; i < detail::count_v; ++i) { - if (value == detail::names_v[i]) { - return enum_value(i); - } - } - - return std::nullopt; // Invalid value or out of range. + return enum_cast(value, detail::char_equal_to{}); } // Obtains enum value from integer value. @@ -729,7 +734,7 @@ template namespace ostream_operators { template , int> = 0> -auto& operator<<(std::basic_ostream& os, E value) { +std::basic_ostream& operator<<(std::basic_ostream& os, E value) { using D = std::decay_t; #if defined(MAGIC_ENUM_SUPPORTED) && MAGIC_ENUM_SUPPORTED using namespace magic_enum; @@ -738,17 +743,14 @@ auto& operator<<(std::basic_ostream& os, E value) { for (const auto c : name) { os.put(c); } - } else { - os << enum_integer(value); + return os; } -#else - os << static_cast(value); #endif - return os; + return os << static_cast(value); } template , int> = 0> -auto& operator<<(std::basic_ostream& os, std::optional value) { +std::basic_ostream& operator<<(std::basic_ostream& os, std::optional value) { if (value.has_value()) { os << value.value(); } @@ -835,11 +837,13 @@ template template [[nodiscard]] auto enum_name(E value) -> detail::enable_if_enum_flags_t { using D = std::decay_t; - using U = std::underlying_type_t; + using U = underlying_type_t; std::string name; + auto check_value = U{0}; for (std::size_t i = 0; i < detail::count_v; ++i) { if (const auto v = enum_value(i); (static_cast(value) & static_cast(v)) != 0) { + check_value |= static_cast(v); const auto n = detail::names_v[i]; if (!name.empty()) { name.append(1, '|'); @@ -848,7 +852,11 @@ template } } - return name; + if (check_value == static_cast(value)) { + return name; + } + + return {}; // Invalid value or out of range. } // Returns std::array with string names, sorted by enum-flags value. @@ -873,7 +881,7 @@ template using D = std::decay_t; if constexpr (detail::is_sparse_v) { - using U = std::underlying_type_t; + using U = underlying_type_t; auto check_value = U{0}; for (std::size_t i = 0; i < detail::count_v; ++i) { if (const auto v = static_cast(enum_value(i)); (static_cast(value) & v) != 0) { @@ -894,7 +902,7 @@ template template [[nodiscard]] constexpr auto enum_contains(E value) noexcept -> detail::enable_if_enum_flags_t { using D = std::decay_t; - using U = std::underlying_type_t; + using U = underlying_type_t; return enum_contains(static_cast(value)); } @@ -962,23 +970,22 @@ using magic_enum::enum_integer; // TODO: impl namespace ostream_operators { template = 0> -auto& operator<<(std::basic_ostream& os, E value) { - using namespace magic_enum::flags; +std::basic_ostream& operator<<(std::basic_ostream& os, E value) { using D = std::decay_t; - +#if defined(MAGIC_ENUM_SUPPORTED) && MAGIC_ENUM_SUPPORTED + using namespace magic_enum::flags; if (const auto name = enum_name(value); !name.empty()) { for (const auto c : name) { os.put(c); } - } else { - os << enum_integer(value); + return os; } - - return os; +#endif + return os << static_cast(value); } template = 0> -auto& operator<<(std::basic_ostream& os, std::optional value) { +std::basic_ostream& operator<<(std::basic_ostream& os, std::optional value) { if (value.has_value()) { os << value.value(); } @@ -990,7 +997,40 @@ auto& operator<<(std::basic_ostream& os, std::optional value) { namespace bitwise_operators { -using namespace magic_enum::bitwise_operators; +template = 0> +constexpr E operator~(E rhs) noexcept { + return static_cast(~static_cast>(rhs)); +} + +template = 0> +constexpr E operator|(E lhs, E rhs) noexcept { + return static_cast(static_cast>(lhs) | static_cast>(rhs)); +} + +template = 0> +constexpr E operator&(E lhs, E rhs) noexcept { + return static_cast(static_cast>(lhs) & static_cast>(rhs)); +} + +template = 0> +constexpr E operator^(E lhs, E rhs) noexcept { + return static_cast(static_cast>(lhs) ^ static_cast>(rhs)); +} + +template = 0> +constexpr E& operator|=(E& lhs, E rhs) noexcept { + return lhs = lhs | rhs; +} + +template = 0> +constexpr E& operator&=(E& lhs, E rhs) noexcept { + return lhs = lhs & rhs; +} + +template = 0> +constexpr E& operator^=(E& lhs, E rhs) noexcept { + return lhs = lhs ^ rhs; +} } // namespace magic_enum::flags::bitwise_operators