Skip to content

Commit

Permalink
Zephyr: Common: make Result<T,U> movable
Browse files Browse the repository at this point in the history
  • Loading branch information
fleroviux committed Jul 8, 2024
1 parent 55c06e0 commit 6af5041
Showing 1 changed file with 25 additions and 0 deletions.
25 changes: 25 additions & 0 deletions zephyr/common/include/zephyr/result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#pragma once

#include <zephyr/panic.hpp>
#include <algorithm>
#include <memory>
#include <type_traits>

Expand All @@ -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<typename StatusCode, typename T>
requires std::is_move_constructible_v<T>
class Result {
Expand All @@ -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();
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 6af5041

Please sign in to comment.