From: Alex Rousskov Date: Thu, 1 Dec 2022 05:49:57 +0000 (+0000) Subject: Make Optional trivially copyable (#1188) X-Git-Tag: SQUID_6_0_1~71 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c5f6c5568788c90a75dcffbd136a7daed2f8e658;p=thirdparty%2Fsquid.git Make Optional trivially copyable (#1188) ipc/TypedMsgHdr.h: static assertion failed: putPod() used for a POD ActionParams.cc:44: required from here [with Pod = RequestFlags] The known XXX in Optional destructor has started to bite us because pending changes expose memcpy(3)-based IPC serialization code to Optional flags. It is possible to mimic standard std::optional implementations, avoiding that XXX, but that requires rather sophisticated C++ tricks with placement new() and such. Specializing the whole Optional is a better alternative for this _temporary_ class IMO. --- diff --git a/src/base/Optional.h b/src/base/Optional.h index a803d30d8c..1c153b99c8 100644 --- a/src/base/Optional.h +++ b/src/base/Optional.h @@ -122,6 +122,53 @@ private: bool hasValue_ = false; }; +/// Specialization to make Optional trivially-copyable. XXX: Keep this +/// temporary (until we switch to C++17 std::optional) hack in sync with the +/// generic Optional above, copying generic methods where possible. +template <> +class Optional +{ +public: + using Value = bool; + + constexpr Optional() noexcept = default; + constexpr explicit Optional(const Value &v): value_(v), hasValue_(true) {} + + constexpr explicit operator bool() const noexcept { return hasValue_; } + constexpr bool has_value() const noexcept { return hasValue_; } + + const Value &value() const & + { + if (!hasValue_) + throw BadOptionalAccess(); + return value_; + } + + template + constexpr Value value_or(Other &&defaultValue) const & + { + return hasValue_ ? value_ : static_cast(std::forward(defaultValue)); + } + + template + Optional &operator =(Other &&otherValue) + { + value_ = std::forward(otherValue); + hasValue_ = true; + return *this; + } + + void reset() { + if (hasValue_) { + hasValue_ = false; + } + } + +private: + Value value_ = false; + bool hasValue_ = false; +}; + template inline std::ostream &operator <<(std::ostream &os, const Optional &opt)