From 19e552861f9321a9c73bc4d3aa5102387772a321 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Thu, 8 Mar 2018 10:25:27 +0100 Subject: Use placement new in Expected when constructing objects --- framework/src/errors.h | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/framework/src/errors.h b/framework/src/errors.h index 9c48f32a..5ee1a667 100644 --- a/framework/src/errors.h +++ b/framework/src/errors.h @@ -84,45 +84,48 @@ struct StorageBase protected: // Rule of 5 {{{ - constexpr void copyPartFromOther(const StorageBase &other) + StorageBase(const StorageBase &other) : mIsValue(other.mIsValue) { + // This is a constructor, you have to construct object, not assign them + // (hence the placement new) if (mIsValue) { - mValue = other.mValue; + new (std::addressof(mValue)) Type(other.mValue); } else { - mError = other.mError; + new (std::addressof(mError)) Unexpected(other.mError); } } - void movePartFromOther(StorageBase &&other) + StorageBase(StorageBase &&other) : mIsValue(other.mIsValue) { + // This is a constructor, you have to construct object, not assign them + // (hence the placement new) if (mIsValue) { - mValue = std::move(other.mValue); + new (std::addressof(mValue)) Type(std::move(other.mValue)); } else { - mError = std::move(other.mError); + new (std::addressof(mError)) Unexpected(std::move(other.mError)); } } - StorageBase(const StorageBase &other) : mIsValue(other.mIsValue) - { - copyPartFromOther(other); - } - - StorageBase(StorageBase &&other) : mIsValue(other.mIsValue) - { - movePartFromOther(std::move(other)); - } - constexpr StorageBase &operator=(const StorageBase &other) { mIsValue = other.mIsValue; - copyPartFromOther(other); + if (mIsValue) { + mValue = other.mValue; + } else { + mError = other.mError; + } return *this; } constexpr StorageBase &operator=(StorageBase &&other) { + this->~StorageBase(); mIsValue = other.mIsValue; - movePartFromOther(other); + if (mIsValue) { + mValue = std::move(other.mValue); + } else { + mError = std::move(other.mError); + } return *this; } @@ -216,6 +219,11 @@ struct ExpectedBase : detail::Storage Q_ASSERT(this->mIsValue); return this->mValue; } + Type &&value() && + { + Q_ASSERT(this->mIsValue); + return std::move(this->mValue); + } }; // Write functions here when dev API related and when Type == void -- cgit v1.2.3