From 9a700b545d7b9b9f4fe9dfb599f79036a97f778e Mon Sep 17 00:00:00 2001 From: neargye Date: Wed, 24 Jul 2019 18:47:36 +0500 Subject: [PATCH] add bitwise_operators --- README.md | 2 +- example/example.cpp | 2 +- include/magic_enum.hpp | 68 +++++++++++++++++++++++++++++++++++++++--- test/test.cpp | 7 +++-- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 95b9724..d97deae 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ enum Color { RED = 2, BLUE = 4, GREEN = 8 }; * Stream operator for enum ```cpp - using namespace magic_enum::ops; // out-of-the-box stream operator for enums. + using namespace magic_enum::ostream_operators; // out-of-the-box ostream operators for enums. Color color = Color::BLUE; std::cout << color << std::endl; // "BLUE" ``` diff --git a/example/example.cpp b/example/example.cpp index c1f5a3c..513d2b8 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -59,7 +59,7 @@ int main() { std::cout << "RED = " << color_integer << std::endl; // RED = -10 } - using namespace magic_enum::ops; // out-of-the-box stream operator for enums. + using namespace magic_enum::ostream_operators; // out-of-the-box ostream operator for enums. // ostream operator for enum. std::cout << "Color: " << c1 << " " << c2 << " " << c3 << std::endl; // Color: RED BLUE GREEN diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 8539b69..12c1abd 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -368,11 +368,11 @@ template > return entries; } -namespace ops { +namespace ostream_operators { template > std::basic_ostream& operator<<(std::basic_ostream& os, E value) { - static_assert(detail::check_enum_v, "magic_enum::ops::operator<< requires enum type."); + static_assert(detail::check_enum_v, "magic_enum::ostream_operators::operator<< requires enum type."); if (auto name = detail::name_impl(static_cast(value)); !name.empty()) { for (auto c : name) { @@ -385,7 +385,7 @@ std::basic_ostream& operator<<(std::basic_ostream& o template > std::basic_ostream& operator<<(std::basic_ostream& os, std::optional value) { - static_assert(detail::check_enum_v, "magic_enum::ops::operator<< requires enum type."); + static_assert(detail::check_enum_v, "magic_enum::ostream_operators::operator<< requires enum type."); if (value.has_value()) { if (auto name = detail::name_impl(static_cast(value.value())); !name.empty()) { @@ -398,7 +398,67 @@ std::basic_ostream& operator<<(std::basic_ostream& o return os; } -} // namespace magic_enum::ops +} // namespace magic_enum::ostream_operators + +namespace bitwise_operators { + +template > +constexpr E operator~(E rhs) { + static_assert(detail::check_enum_v, "magic_enum::bitwise_operators::operator~ requires enum type."); + using U = std::underlying_type_t; + + return static_cast(~static_cast(rhs)); +} + +template > +constexpr E operator|(E lhs, E rhs) { + static_assert(detail::check_enum_v, "magic_enum::bitwise_operators::operator| requires enum type."); + using U = std::underlying_type_t; + + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +template > +constexpr E operator&(E lhs, E rhs) { + static_assert(detail::check_enum_v, "magic_enum::bitwise_operators::operator& requires enum type."); + using U = std::underlying_type_t; + + return static_cast(static_cast(lhs) & static_cast(rhs)); +} + +template > +constexpr E operator^(E lhs, E rhs) { + static_assert(detail::check_enum_v, "magic_enum::bitwise_operators::operator^ requires enum type."); + using U = std::underlying_type_t; + + return static_cast(static_cast(lhs) ^ static_cast(rhs)); +} + +template > +constexpr E& operator|=(E& lhs, E rhs) { + static_assert(detail::check_enum_v, "magic_enum::bitwise_operators::operator|= requires enum type."); + using U = std::underlying_type_t; + + return lhs = static_cast(static_cast(lhs) | static_cast(rhs)); +} + +template > +constexpr E& operator&=(E& lhs, E rhs) { + static_assert(detail::check_enum_v, "magic_enum::bitwise_operators::operator%= requires enum type."); + using U = std::underlying_type_t; + + return lhs = static_cast(static_cast(lhs) & static_cast(rhs)); +} + +template > +constexpr E& operator^=(E& lhs, E rhs) { + static_assert(detail::check_enum_v, "magic_enum::bitwise_operators::operator^= requires enum type."); + using U = std::underlying_type_t; + + return lhs = static_cast(static_cast(lhs) ^ static_cast(rhs)); +} + +} // namespace magic_enum::bitwise_operators } // namespace magic_enum diff --git a/test/test.cpp b/test/test.cpp index 49deb2b..06c5b4a 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -291,9 +291,9 @@ TEST_CASE("enum_entries") { REQUIRE(s4 == std::array, 3>{{{number::one, "one"}, {number::two, "two"}, {number::three, "three"}}}); } -TEST_CASE("operator<<") { +TEST_CASE("ostream_operators") { auto test_ostream = [](auto e, std::string_view name) { - using namespace magic_enum::ops; + using namespace magic_enum::ostream_operators; std::stringstream ss; ss << e; REQUIRE(ss.str() == name); @@ -323,6 +323,9 @@ TEST_CASE("operator<<") { test_ostream(static_cast(0), ""); } +TEST_CASE("bitwise_operators") { +} + TEST_CASE("type_traits") { REQUIRE_FALSE(magic_enum::is_unscoped_enum_v); REQUIRE_FALSE(magic_enum::is_unscoped_enum_v);