diff --git a/code/turboq/BoundedMPSCRawQueue.h b/code/turboq/BoundedMPSCRawQueue.h index 31db610..9cd0970 100644 --- a/code/turboq/BoundedMPSCRawQueue.h +++ b/code/turboq/BoundedMPSCRawQueue.h @@ -167,7 +167,7 @@ class BoundedMPSCRawQueueProducer { std::size_t const totalSize = size + sizeof(MessageHeader); if (totalSize > header_->maxMessageSize) [[unlikely]] { throw std::runtime_error( - std::format("buffer exceed max message size ({} > {})", totalSize, header_->maxMessageSize)); + fmt::format("buffer exceed max message size ({} > {})", totalSize, header_->maxMessageSize)); } std::size_t currentProducerPos = std::atomic_ref(header_->producerPos).load(std::memory_order_acquire); diff --git a/code/turboq/detail/Expected.h b/code/turboq/detail/Expected.h index ca88a50..1e67c83 100644 --- a/code/turboq/detail/Expected.h +++ b/code/turboq/detail/Expected.h @@ -2,6 +2,7 @@ // SPDX-License-Identifier: AGPL-3.0 #include +#include #include #include @@ -17,7 +18,9 @@ template class Unexpected { public: constexpr Unexpected(Unexpected const&) = default; + constexpr Unexpected& operator=(Unexpected const&) = default; constexpr Unexpected(Unexpected&&) = default; + constexpr Unexpected& operator=(Unexpected&&) = default; constexpr explicit Unexpected(E const& rhs) : storage_(rhs) {} constexpr explicit Unexpected(E&& rhs) : storage_(std::move(rhs)) {} @@ -29,6 +32,9 @@ class Unexpected { return std::move(storage_); } + friend constexpr bool operator==(Unexpected const&, Unexpected const&) = default; + friend constexpr auto operator<=>(Unexpected const&, Unexpected const&) = default; + private: E storage_; }; @@ -49,7 +55,40 @@ class Expected { constexpr Expected(Args&&... args) : storage_(std::forward(args)...) {} constexpr Expected(Expected const&) = default; + constexpr Expected& operator=(Expected const&) = default; constexpr Expected(Expected&&) = default; + constexpr Expected& operator=(Expected&&) = default; + + constexpr Expected& operator=(T&& value) { + storage_.template emplace<0>(std::move(value)); + return *this; + } + + constexpr Expected& operator=(T const& value) { + storage_.template emplace<0>(value); + return *this; + } + + constexpr Expected& operator=(Unexpected&& value) { + storage_.template emplace<1>(std::move(value)); + return *this; + } + + constexpr Expected& operator=(Unexpected const& value) { + storage_.template emplace<1>(value); + return *this; + } + + template + requires(!std::is_same_v, Expected> && std::is_convertible_v && std::is_convertible_v) + constexpr Expected& operator=(Expected value) { + if (value.has_value()) { + storage_.template emplace<0>(std::move(static_cast&&>(value).value())); + } else { + storage_.template emplace<1>(std::move(static_cast&&>(value).error())); + } + return *this; + } constexpr bool has_value() const noexcept { return storage_.index() == 0; @@ -106,7 +145,20 @@ class Expected { constexpr Expected(Args&&... args) : storage_(std::forward(args)...) {} constexpr Expected(Expected const&) = default; + constexpr Expected& operator=(Expected const&) = default; constexpr Expected(Expected&&) = default; + constexpr Expected& operator=(Expected&&) = default; + + template + requires std::is_convertible_v + constexpr Expected& operator=(Expected value) { + if (!value.has_value()) { + storage_.template emplace<1>(std::move(static_cast&&>(value).error())); + } else { + storage_.template emplace<0>(); + } + return *this; + } constexpr bool has_value() const noexcept { return storage_.index() == 0; @@ -123,6 +175,16 @@ class Expected { constexpr E error() && noexcept { return std::move(*std::get_if>(&storage_)).error(); } + + constexpr Expected& operator=(Unexpected&& value) { + storage_.template emplace<1>(std::move(value)); + return *this; + } + + constexpr Expected& operator=(Unexpected const& value) { + storage_.template emplace<1>(value); + return *this; + } }; } // namespace turboq::detail