Skip to content

Commit 99d98dd

Browse files
committed
Improved enum flags operators and tests
1 parent 9a60ad3 commit 99d98dd

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-4
lines changed

tests/socket.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,27 @@ TEST_CASE("socket swap", "[socket]")
4646
using std::swap;
4747
swap(socket1, socket2);
4848
}
49-
TEST_CASE("rass", "[socket]")
49+
50+
TEST_CASE("socket flags", "[socket]")
51+
{
52+
CHECK((zmq::recv_flags::dontwait | zmq::recv_flags::none)
53+
== static_cast<zmq::recv_flags>(ZMQ_DONTWAIT | 0));
54+
CHECK((zmq::recv_flags::dontwait & zmq::recv_flags::none)
55+
== static_cast<zmq::recv_flags>(ZMQ_DONTWAIT & 0));
56+
CHECK((zmq::recv_flags::dontwait ^ zmq::recv_flags::none)
57+
== static_cast<zmq::recv_flags>(ZMQ_DONTWAIT ^ 0));
58+
CHECK(~zmq::recv_flags::dontwait == static_cast<zmq::recv_flags>(~ZMQ_DONTWAIT));
59+
60+
CHECK((zmq::send_flags::dontwait | zmq::send_flags::sndmore)
61+
== static_cast<zmq::send_flags>(ZMQ_DONTWAIT | ZMQ_SNDMORE));
62+
CHECK((zmq::send_flags::dontwait & zmq::send_flags::sndmore)
63+
== static_cast<zmq::send_flags>(ZMQ_DONTWAIT & ZMQ_SNDMORE));
64+
CHECK((zmq::send_flags::dontwait ^ zmq::send_flags::sndmore)
65+
== static_cast<zmq::send_flags>(ZMQ_DONTWAIT ^ ZMQ_SNDMORE));
66+
CHECK(~zmq::send_flags::dontwait == static_cast<zmq::send_flags>(~ZMQ_DONTWAIT));
67+
}
68+
69+
TEST_CASE("socket readme example", "[socket]")
5070
{
5171
zmq::context_t ctx;
5272
zmq::socket_t sock(ctx, zmq::socket_type::push);

zmq.hpp

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,39 @@ struct recv_buffer_result
645645
}
646646
};
647647

648+
namespace detail
649+
{
650+
template<class T>
651+
constexpr T enum_bit_or(T a, T b) noexcept
652+
{
653+
static_assert(std::is_enum<T>::value, "must be enum");
654+
using U = typename std::underlying_type<T>::type;
655+
return static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
656+
}
657+
template<class T>
658+
constexpr T enum_bit_and(T a, T b) noexcept
659+
{
660+
static_assert(std::is_enum<T>::value, "must be enum");
661+
using U = typename std::underlying_type<T>::type;
662+
return static_cast<T>(static_cast<U>(a) & static_cast<U>(b));
663+
}
664+
template<class T>
665+
constexpr T enum_bit_xor(T a, T b) noexcept
666+
{
667+
static_assert(std::is_enum<T>::value, "must be enum");
668+
using U = typename std::underlying_type<T>::type;
669+
return static_cast<T>(static_cast<U>(a) ^ static_cast<U>(b));
670+
}
671+
template<class T>
672+
constexpr T enum_bit_not(T a) noexcept
673+
{
674+
static_assert(std::is_enum<T>::value, "must be enum");
675+
using U = typename std::underlying_type<T>::type;
676+
return static_cast<T>(~static_cast<U>(a));
677+
}
678+
} // namespace detail
679+
680+
// partially satisfies named requirement BitmaskType
648681
enum class send_flags : int
649682
{
650683
none = 0,
@@ -654,10 +687,22 @@ enum class send_flags : int
654687

655688
constexpr send_flags operator|(send_flags a, send_flags b) noexcept
656689
{
657-
return static_cast<send_flags>(static_cast<std::underlying_type<send_flags>::type>(a)
658-
| static_cast<<std::underlying_type<send_flags>::type>(b));
690+
return detail::enum_bit_or(a, b);
691+
}
692+
constexpr send_flags operator&(send_flags a, send_flags b) noexcept
693+
{
694+
return detail::enum_bit_and(a, b);
695+
}
696+
constexpr send_flags operator^(send_flags a, send_flags b) noexcept
697+
{
698+
return detail::enum_bit_xor(a, b);
699+
}
700+
constexpr send_flags operator~(send_flags a) noexcept
701+
{
702+
return detail::enum_bit_not(a);
659703
}
660704

705+
// partially satisfies named requirement BitmaskType
661706
enum class recv_flags : int
662707
{
663708
none = 0,
@@ -666,8 +711,21 @@ enum class recv_flags : int
666711

667712
constexpr recv_flags operator|(recv_flags a, recv_flags b) noexcept
668713
{
669-
return static_cast<recv_flags>(static_cast<int>(a) | static_cast<int>(b));
714+
return detail::enum_bit_or(a, b);
715+
}
716+
constexpr recv_flags operator&(recv_flags a, recv_flags b) noexcept
717+
{
718+
return detail::enum_bit_and(a, b);
719+
}
720+
constexpr recv_flags operator^(recv_flags a, recv_flags b) noexcept
721+
{
722+
return detail::enum_bit_xor(a, b);
670723
}
724+
constexpr recv_flags operator~(recv_flags a) noexcept
725+
{
726+
return detail::enum_bit_not(a);
727+
}
728+
671729

672730
// mutable_buffer, const_buffer and buffer are based on
673731
// the Networking TS specification, draft:

0 commit comments

Comments
 (0)