72
72
#include < cassert>
73
73
#include < cstring>
74
74
75
- #ifdef ZMQ_CPP11
76
- #include < array>
77
- #endif
78
75
#include < algorithm>
79
76
#include < exception>
80
77
#include < iomanip>
81
- #include < iterator>
82
78
#include < sstream>
83
79
#include < string>
84
80
#include < vector>
81
+ #ifdef ZMQ_CPP11
82
+ #include < array>
83
+ #include < chrono>
84
+ #include < tuple>
85
+ #include < memory>
86
+ #endif
87
+ #ifdef ZMQ_CPP17
88
+ #include < optional>
89
+ #endif
85
90
86
91
/* Version macros for compile-time API version detection */
87
92
#define CPPZMQ_VERSION_MAJOR 4
92
97
ZMQ_MAKE_VERSION (CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR, \
93
98
CPPZMQ_VERSION_PATCH)
94
99
95
- #ifdef ZMQ_CPP11
96
- #include < chrono>
97
- #include < tuple>
98
- #include < memory>
99
- #endif
100
-
101
100
// Detect whether the compiler supports C++11 rvalue references.
102
101
#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) \
103
102
&& defined(__GXX_EXPERIMENTAL_CXX0X__))
@@ -621,23 +620,11 @@ inline void swap(context_t &a, context_t &b) ZMQ_NOTHROW {
621
620
}
622
621
623
622
#ifdef ZMQ_CPP11
624
- struct send_result
625
- {
626
- size_t size; // message size in bytes
627
- bool success;
628
- };
629
-
630
- struct recv_result
631
- {
632
- size_t size; // message size in bytes
633
- bool success;
634
- };
635
623
636
- struct recv_buffer_result
624
+ struct recv_buffer_size
637
625
{
638
626
size_t size; // number of bytes written to buffer
639
627
size_t untruncated_size; // untruncated message size in bytes
640
- bool success;
641
628
642
629
ZMQ_NODISCARD bool truncated () const noexcept
643
630
{
@@ -647,6 +634,71 @@ struct recv_buffer_result
647
634
648
635
namespace detail
649
636
{
637
+
638
+ #ifdef ZMQ_CPP17
639
+ using send_result_t = std::optional<size_t >;
640
+ using recv_result_t = std::optional<size_t >;
641
+ using recv_buffer_result_t = std::optional<recv_buffer_size>;
642
+ #else
643
+ // A C++11 type emulating the most basic
644
+ // operations of std::optional for trivial types
645
+ template <class T > class trivial_optional
646
+ {
647
+ public:
648
+ static_assert (std::is_trivial<T>::value, " T must be trivial" );
649
+ using value_type = T;
650
+
651
+ trivial_optional () = default ;
652
+ trivial_optional (T value) noexcept : _value(value), _has_value(true ) {}
653
+
654
+ const T *operator ->() const noexcept
655
+ {
656
+ assert (_has_value);
657
+ return &_value;
658
+ }
659
+ T *operator ->() noexcept
660
+ {
661
+ assert (_has_value);
662
+ return &_value;
663
+ }
664
+
665
+ const T &operator *() const noexcept
666
+ {
667
+ assert (_has_value);
668
+ return _value;
669
+ }
670
+ T &operator *() noexcept
671
+ {
672
+ assert (_has_value);
673
+ return _value;
674
+ }
675
+
676
+ T &value ()
677
+ {
678
+ if (!_has_value)
679
+ throw std::exception ();
680
+ return _value;
681
+ }
682
+ const T &value () const
683
+ {
684
+ if (!_has_value)
685
+ throw std::exception ();
686
+ return _value;
687
+ }
688
+
689
+ explicit operator bool () const noexcept { return _has_value; }
690
+ bool has_value () const noexcept { return _has_value; }
691
+
692
+ private:
693
+ T _value{};
694
+ bool _has_value{false };
695
+ };
696
+
697
+ using send_result_t = trivial_optional<size_t >;
698
+ using recv_result_t = trivial_optional<size_t >;
699
+ using recv_buffer_result_t = trivial_optional<recv_buffer_size>;
700
+ #endif
701
+
650
702
template <class T >
651
703
constexpr T enum_bit_or (T a, T b) noexcept
652
704
{
@@ -1111,36 +1163,36 @@ class socket_base
1111
1163
int flags_ = 0 ) // default until removed
1112
1164
{
1113
1165
#ifdef ZMQ_CPP11
1114
- return send (msg_, static_cast <send_flags>(flags_)).success ;
1166
+ return send (msg_, static_cast <send_flags>(flags_)).has_value () ;
1115
1167
#else
1116
1168
return send (msg_, flags_);
1117
1169
#endif
1118
1170
}
1119
1171
#endif
1120
1172
1121
1173
#ifdef ZMQ_CPP11
1122
- send_result send (const_buffer buf, send_flags flags = send_flags::none)
1174
+ detail:: send_result_t send (const_buffer buf, send_flags flags = send_flags::none)
1123
1175
{
1124
1176
const int nbytes =
1125
1177
zmq_send (_handle, buf.data (), buf.size (), static_cast <int >(flags));
1126
1178
if (nbytes >= 0 )
1127
- return { static_cast <size_t >(nbytes), true } ;
1179
+ return static_cast <size_t >(nbytes);
1128
1180
if (zmq_errno () == EAGAIN)
1129
- return {size_t { 0 }, false };
1181
+ return {};
1130
1182
throw error_t ();
1131
1183
}
1132
1184
1133
- send_result send (message_t &msg, send_flags flags)
1185
+ detail:: send_result_t send (message_t &msg, send_flags flags)
1134
1186
{
1135
1187
int nbytes = zmq_msg_send (msg.handle (), _handle, static_cast <int >(flags));
1136
1188
if (nbytes >= 0 )
1137
- return { static_cast <size_t >(nbytes), true } ;
1189
+ return static_cast <size_t >(nbytes);
1138
1190
if (zmq_errno () == EAGAIN)
1139
- return {size_t { 0 }, false };
1191
+ return {};
1140
1192
throw error_t ();
1141
1193
}
1142
1194
1143
- send_result send (message_t &&msg, send_flags flags)
1195
+ detail:: send_result_t send (message_t &&msg, send_flags flags)
1144
1196
{
1145
1197
return send (msg, flags);
1146
1198
}
@@ -1177,27 +1229,29 @@ class socket_base
1177
1229
}
1178
1230
1179
1231
#ifdef ZMQ_CPP11
1180
- recv_buffer_result recv (mutable_buffer buf, recv_flags flags = recv_flags::none)
1232
+ detail::recv_buffer_result_t recv (mutable_buffer buf,
1233
+ recv_flags flags = recv_flags::none)
1181
1234
{
1182
1235
const int nbytes =
1183
1236
zmq_recv (_handle, buf.data (), buf.size (), static_cast <int >(flags));
1184
- if (nbytes >= 0 )
1185
- return {(std::min)(static_cast <size_t >(nbytes), buf.size ()),
1186
- static_cast <size_t >(nbytes), true };
1237
+ if (nbytes >= 0 ) {
1238
+ return recv_buffer_size{(std::min)(static_cast <size_t >(nbytes), buf.size ()),
1239
+ static_cast <size_t >(nbytes)};
1240
+ }
1187
1241
if (zmq_errno () == EAGAIN)
1188
- return {size_t { 0 }, size_t { 0 }, false };
1242
+ return {};
1189
1243
throw error_t ();
1190
1244
}
1191
1245
1192
- recv_result recv (message_t &msg, recv_flags flags = recv_flags::none)
1246
+ detail:: recv_result_t recv (message_t &msg, recv_flags flags = recv_flags::none)
1193
1247
{
1194
1248
const int nbytes = zmq_msg_recv (msg.handle (), _handle, static_cast <int >(flags));
1195
1249
if (nbytes >= 0 ) {
1196
1250
assert (msg.size () == static_cast <size_t >(nbytes));
1197
- return { static_cast <size_t >(nbytes), true } ;
1251
+ return static_cast <size_t >(nbytes);
1198
1252
}
1199
1253
if (zmq_errno () == EAGAIN)
1200
- return {size_t { 0 }, false };
1254
+ return {};
1201
1255
throw error_t ();
1202
1256
}
1203
1257
#endif
0 commit comments