From 99d98dd217d1fb6767a964aa3f2ea194ebf1f109 Mon Sep 17 00:00:00 2001 From: Gudmundur Adalsteinsson Date: Thu, 9 May 2019 22:33:49 +0000 Subject: [PATCH] Improved enum flags operators and tests --- tests/socket.cpp | 22 ++++++++++++++++- zmq.hpp | 64 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/tests/socket.cpp b/tests/socket.cpp index 80962b1..92e7893 100644 --- a/tests/socket.cpp +++ b/tests/socket.cpp @@ -46,7 +46,27 @@ TEST_CASE("socket swap", "[socket]") using std::swap; swap(socket1, socket2); } -TEST_CASE("rass", "[socket]") + +TEST_CASE("socket flags", "[socket]") +{ + CHECK((zmq::recv_flags::dontwait | zmq::recv_flags::none) + == static_cast(ZMQ_DONTWAIT | 0)); + CHECK((zmq::recv_flags::dontwait & zmq::recv_flags::none) + == static_cast(ZMQ_DONTWAIT & 0)); + CHECK((zmq::recv_flags::dontwait ^ zmq::recv_flags::none) + == static_cast(ZMQ_DONTWAIT ^ 0)); + CHECK(~zmq::recv_flags::dontwait == static_cast(~ZMQ_DONTWAIT)); + + CHECK((zmq::send_flags::dontwait | zmq::send_flags::sndmore) + == static_cast(ZMQ_DONTWAIT | ZMQ_SNDMORE)); + CHECK((zmq::send_flags::dontwait & zmq::send_flags::sndmore) + == static_cast(ZMQ_DONTWAIT & ZMQ_SNDMORE)); + CHECK((zmq::send_flags::dontwait ^ zmq::send_flags::sndmore) + == static_cast(ZMQ_DONTWAIT ^ ZMQ_SNDMORE)); + CHECK(~zmq::send_flags::dontwait == static_cast(~ZMQ_DONTWAIT)); +} + +TEST_CASE("socket readme example", "[socket]") { zmq::context_t ctx; zmq::socket_t sock(ctx, zmq::socket_type::push); diff --git a/zmq.hpp b/zmq.hpp index c3d262e..f8acb29 100644 --- a/zmq.hpp +++ b/zmq.hpp @@ -645,6 +645,39 @@ struct recv_buffer_result } }; +namespace detail +{ +template +constexpr T enum_bit_or(T a, T b) noexcept +{ + static_assert(std::is_enum::value, "must be enum"); + using U = typename std::underlying_type::type; + return static_cast(static_cast(a) | static_cast(b)); +} +template +constexpr T enum_bit_and(T a, T b) noexcept +{ + static_assert(std::is_enum::value, "must be enum"); + using U = typename std::underlying_type::type; + return static_cast(static_cast(a) & static_cast(b)); +} +template +constexpr T enum_bit_xor(T a, T b) noexcept +{ + static_assert(std::is_enum::value, "must be enum"); + using U = typename std::underlying_type::type; + return static_cast(static_cast(a) ^ static_cast(b)); +} +template +constexpr T enum_bit_not(T a) noexcept +{ + static_assert(std::is_enum::value, "must be enum"); + using U = typename std::underlying_type::type; + return static_cast(~static_cast(a)); +} +} // namespace detail + +// partially satisfies named requirement BitmaskType enum class send_flags : int { none = 0, @@ -654,10 +687,22 @@ enum class send_flags : int constexpr send_flags operator|(send_flags a, send_flags b) noexcept { - return static_cast(static_cast::type>(a) - | static_cast<::type>(b)); + return detail::enum_bit_or(a, b); +} +constexpr send_flags operator&(send_flags a, send_flags b) noexcept +{ + return detail::enum_bit_and(a, b); +} +constexpr send_flags operator^(send_flags a, send_flags b) noexcept +{ + return detail::enum_bit_xor(a, b); +} +constexpr send_flags operator~(send_flags a) noexcept +{ + return detail::enum_bit_not(a); } +// partially satisfies named requirement BitmaskType enum class recv_flags : int { none = 0, @@ -666,8 +711,21 @@ enum class recv_flags : int constexpr recv_flags operator|(recv_flags a, recv_flags b) noexcept { - return static_cast(static_cast(a) | static_cast(b)); + return detail::enum_bit_or(a, b); } +constexpr recv_flags operator&(recv_flags a, recv_flags b) noexcept +{ + return detail::enum_bit_and(a, b); +} +constexpr recv_flags operator^(recv_flags a, recv_flags b) noexcept +{ + return detail::enum_bit_xor(a, b); +} +constexpr recv_flags operator~(recv_flags a) noexcept +{ + return detail::enum_bit_not(a); +} + // mutable_buffer, const_buffer and buffer are based on // the Networking TS specification, draft: