7272#include < cassert>
7373#include < cstring>
7474
75- #ifdef ZMQ_CPP11
76- #include < array>
77- #endif
7875#include < algorithm>
7976#include < exception>
8077#include < iomanip>
81- #include < iterator>
8278#include < sstream>
8379#include < string>
8480#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
8590
8691/* Version macros for compile-time API version detection */
8792#define CPPZMQ_VERSION_MAJOR 4
9297 ZMQ_MAKE_VERSION (CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR, \
9398 CPPZMQ_VERSION_PATCH)
9499
95- #ifdef ZMQ_CPP11
96- #include < chrono>
97- #include < tuple>
98- #include < memory>
99- #endif
100-
101100// Detect whether the compiler supports C++11 rvalue references.
102101#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) \
103102 && defined (__GXX_EXPERIMENTAL_CXX0X__))
@@ -621,23 +620,11 @@ inline void swap(context_t &a, context_t &b) ZMQ_NOTHROW {
621620}
622621
623622#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- };
635623
636- struct recv_buffer_result
624+ struct recv_buffer_size
637625{
638626 size_t size; // number of bytes written to buffer
639627 size_t untruncated_size; // untruncated message size in bytes
640- bool success;
641628
642629 ZMQ_NODISCARD bool truncated () const noexcept
643630 {
@@ -647,6 +634,71 @@ struct recv_buffer_result
647634
648635namespace detail
649636{
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+
650702template <class T >
651703constexpr T enum_bit_or (T a, T b) noexcept
652704{
@@ -1111,36 +1163,36 @@ class socket_base
11111163 int flags_ = 0 ) // default until removed
11121164 {
11131165 #ifdef ZMQ_CPP11
1114- return send (msg_, static_cast <send_flags>(flags_)).success ;
1166+ return send (msg_, static_cast <send_flags>(flags_)).has_value () ;
11151167 #else
11161168 return send (msg_, flags_);
11171169 #endif
11181170 }
11191171#endif
11201172
11211173#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)
11231175 {
11241176 const int nbytes =
11251177 zmq_send (_handle, buf.data (), buf.size (), static_cast <int >(flags));
11261178 if (nbytes >= 0 )
1127- return { static_cast <size_t >(nbytes), true } ;
1179+ return static_cast <size_t >(nbytes);
11281180 if (zmq_errno () == EAGAIN)
1129- return {size_t { 0 }, false };
1181+ return {};
11301182 throw error_t ();
11311183 }
11321184
1133- send_result send (message_t &msg, send_flags flags)
1185+ detail:: send_result_t send (message_t &msg, send_flags flags)
11341186 {
11351187 int nbytes = zmq_msg_send (msg.handle (), _handle, static_cast <int >(flags));
11361188 if (nbytes >= 0 )
1137- return { static_cast <size_t >(nbytes), true } ;
1189+ return static_cast <size_t >(nbytes);
11381190 if (zmq_errno () == EAGAIN)
1139- return {size_t { 0 }, false };
1191+ return {};
11401192 throw error_t ();
11411193 }
11421194
1143- send_result send (message_t &&msg, send_flags flags)
1195+ detail:: send_result_t send (message_t &&msg, send_flags flags)
11441196 {
11451197 return send (msg, flags);
11461198 }
@@ -1177,27 +1229,29 @@ class socket_base
11771229 }
11781230
11791231#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)
11811234 {
11821235 const int nbytes =
11831236 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+ }
11871241 if (zmq_errno () == EAGAIN)
1188- return {size_t { 0 }, size_t { 0 }, false };
1242+ return {};
11891243 throw error_t ();
11901244 }
11911245
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)
11931247 {
11941248 const int nbytes = zmq_msg_recv (msg.handle (), _handle, static_cast <int >(flags));
11951249 if (nbytes >= 0 ) {
11961250 assert (msg.size () == static_cast <size_t >(nbytes));
1197- return { static_cast <size_t >(nbytes), true } ;
1251+ return static_cast <size_t >(nbytes);
11981252 }
11991253 if (zmq_errno () == EAGAIN)
1200- return {size_t { 0 }, false };
1254+ return {};
12011255 throw error_t ();
12021256 }
12031257#endif
0 commit comments