Improve constexpr coverage in zmq.hpp with C++11/14/17 compatibility#684
Improve constexpr coverage in zmq.hpp with C++11/14/17 compatibility#684mberk-yilmaz wants to merge 8 commits intozeromq:masterfrom
Conversation
Add const-qualified overloads for multipart_t::front() and back() in `zmq_addon.hpp`. Note on API shape: - In a container-style API, non-const overloads would typically return `message_t&`. - This change intentionally preserves existing non-const return types (`const message_t&`) for backward-compatibility and to avoid broadening mutability semantics in this PR. Also extend `tests/multipart.cpp` with compile-time and runtime checks for const/non-const access paths. No behavioral change intended.
…ionally added test for constexpr.
- map ZMQ_EXTENDED_CONSTEXPR to constexpr under existing compiler guards - add constexpr to safe state observers in context_t/socket_base/socket_ref paths - add constexpr to recv_buffer_size::truncated and fallback trivial_optional observers/ctor - strengthen compile-time tests with static_assert checks in context/socket/socket_ref tests - keep risky/non-portable areas (buffer pointer arithmetic, pointer ordering semantics) unchanged
Pull Request Test Coverage Report for Build 23746422095Details
💛 - Coveralls |
|
Why these two ways of marking functions constexpr? // why not just use ZMQ_CONSTEXPR_FN?
// or if there is need why not just ZMQ_EXTENDED_CONSTEXPR operator void *() ZMQ_NOTHROW { return _handle; }
#ifdef ZMQ_EXTENDED_CONSTEXPR
ZMQ_EXTENDED_CONSTEXPR operator void *() ZMQ_NOTHROW { return _handle; }
#else
operator void *() ZMQ_NOTHROW { return _handle; }
#endif
ZMQ_CONSTEXPR_FN operator void const *() const ZMQ_NOTHROW { return _handle; }Related to this it's interesting to still support C++98 with C++26 releasing this year. |
zmq.hpp
Outdated
| @@ -965,7 +986,10 @@ template<class T> class trivial_optional | |||
| using value_type = T; | |||
|
|
|||
| trivial_optional() = default; | |||
There was a problem hiding this comment.
For intent, yes, for behavior there is no difference.
As cppreference states:
"If it satisfies the requirements of a constexpr constructor (until C++23) / constexpr function (since C++23), the generated constructor is constexpr."
| inline ZMQ_CONSTEXPR_FN bool operator==(const detail::socket_base &a, | ||
| const detail::socket_base &b) ZMQ_NOTHROW | ||
| { | ||
| return std::equal_to<const void *>()(a.handle(), b.handle()); |
There was a problem hiding this comment.
std::equal_to<T>::operator() is constexpr only since C++14.
So in C++11 mode it cannot be used in a ZMQ_CONSTEXPR_FN function body.
Also, pointer equality (==) is well-defined and not UB. Why do you think it's UB?
There was a problem hiding this comment.
Ok you are correct this is fine. The confusion is that comparing possibly unrelated pointers with < is unspecified unless using std::less.
operator void*() in socket_t was missing the #ifdef ZMQ_EXTENDED_CONSTEXPR guard present on all other uses of the macro, causing a compilation error when built with C++11 where the macro is not defined.
| std::swap(msg, other.msg); | ||
| } | ||
|
|
||
| #ifdef ZMQ_EXTENDED_CONSTEXPR |
There was a problem hiding this comment.
All these #ifdef ZMQ_EXTENDED_CONSTEXPR branches can be removed
What changed
This PR expands
constexprusage inzmq.hppwith a compatibility-first approach across C++11/14/17.zmq.hppZMQ_EXTENDED_CONSTEXPRasconstexpr(under existing compiler/version guards).constexpron safe pointer-state observers:context_t::operator bool() constdetail::socket_base::handle() constdetail::socket_base::operator bool() constdetail::socket_base::connected() constconstexpronly whenZMQ_EXTENDED_CONSTEXPRis available.socket_refnull-comparison operatorsconstexpr.detail::socket_baseoperator==/operator!=constexprand use direct pointer equality.recv_buffer_size::truncated()detail::trivial_optional<T>value constructor,operator bool(),has_value().Tests
static_assert:tests/socket.cpp:socket_baseconstexpr handle/bool checkstests/socket_ref.cpp: constexpr null comparison checkstests/context.cpp: constexpr checks forrecv_buffer_size::truncated()and fallbacktrivial_optional(!CPPZMQ_HAS_OPTIONAL)Why this is safe
constexpr; changes are limited to trivial observers/value-state helpers.extended constexprremains opt-in by language/compiler capability.Compatibility notes
ZMQ_EXTENDED_CONSTEXPRremain respected.Validation
Validated by building and testing in three standards: