From 6af50414c3a6f1e28372eaabb12d66d67c645db3 Mon Sep 17 00:00:00 2001 From: fleroviux Date: Mon, 8 Jul 2024 23:21:33 +0200 Subject: [PATCH] Zephyr: Common: make Result movable --- zephyr/common/include/zephyr/result.hpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/zephyr/common/include/zephyr/result.hpp b/zephyr/common/include/zephyr/result.hpp index dad8108..d532be8 100644 --- a/zephyr/common/include/zephyr/result.hpp +++ b/zephyr/common/include/zephyr/result.hpp @@ -2,6 +2,7 @@ #pragma once #include +#include #include #include @@ -10,6 +11,13 @@ namespace zephyr { #define ZEPHYR_RESULT_EMPTY (-1) #define ZEPHYR_RESULT_SUCCESS 0 + #define ZEPHYR_FORWARD_ERROR(result) do { \ + const auto status_code = (result).Code(); \ + if(status_code != ZEPHYR_RESULT_SUCCESS) { \ + return status_code;\ + } \ + } while(0) + template requires std::is_move_constructible_v class Result { @@ -20,6 +28,12 @@ namespace zephyr { Result(T&& value) : m_status_code{(StatusCode)ZEPHYR_RESULT_SUCCESS}, m_value{std::move(value)} {} + Result(const Result&) = delete; + + Result(Result&& other_result) { + operator=(other_result); + } + ~Result() { // needed if `T` has a non-trivial destructor since m_value is in a union if(Ok()) { m_value.~T(); @@ -50,6 +64,17 @@ namespace zephyr { return std::move(m_value); } + Result& operator=(const Result&) = delete; + + Result& operator=(Result&& other_result) noexcept { + std::swap(m_status_code, other_result.m_status_code); + + // As per C++11 standard a union member can only be initialized either during + // initialization of the union or via placement-new. See: https://stackoverflow.com/a/33058919 + new (&m_value) T(std::move(other_result.m_value)); + return *this; + } + private: StatusCode m_status_code{}; union { // Union used to avoid default initialization