dmtools/lib/base/ErrorOr.hpp

105 lines
2.3 KiB
C++
Raw Permalink Normal View History

// Copyright 2024 The DMBMX2Tools Authors
// SPDX-License-Identifier: MIT
#pragma once
#include <optional>
#include <system_error>
#include <variant>
namespace dmtools {
template <class T>
struct ErrorOr {
private:
using Variant = std::variant<T, std::error_code>;
public:
constexpr static auto IsVoid = false;
ErrorOr() = default;
ErrorOr(const ErrorOr&) = default;
ErrorOr(ErrorOr&&) = default;
ErrorOr(const T& v)
: maybeVariant(v) {}
ErrorOr(const std::error_code& v)
: maybeVariant(v) {}
ErrorOr& operator=(const T& value) {
maybeVariant = value;
return *this;
}
ErrorOr& operator=(const std::error_code& ec) {
maybeVariant = ec;
return *this;
}
bool HasValue() const {
if(maybeVariant)
return std::holds_alternative<T>(*maybeVariant);
// No value.
return false;
}
bool HasError() const {
if(maybeVariant)
return std::holds_alternative<std::error_code>(*maybeVariant);
// No error. Possibly in the default constructed state
return false;
}
// ASSERT TODO
T& Value() { return std::get<T>(maybeVariant.value()); }
const T& Value() const { return std::get<T>(maybeVariant.value()); }
operator T&() { return Value(); }
operator const T&() { return Value(); }
std::error_code& Error() { return std::get<std::error_code>(maybeVariant.value()); }
const std::error_code& Error() const { return std::get<std::error_code>(maybeVariant.value()); }
operator std::error_code&() { return Error(); }
operator const std::error_code&() const { return Error(); }
private:
std::optional<Variant> maybeVariant;
};
template <>
struct ErrorOr<void> {
constexpr static auto IsVoid = true;
ErrorOr() = default;
ErrorOr(const ErrorOr&) = default;
ErrorOr(ErrorOr&&) = default;
ErrorOr(const std::error_code& v)
: maybeEc(v) {}
ErrorOr& operator=(const std::error_code& ec) {
maybeEc = ec;
return *this;
}
bool HasError() const { return maybeEc.has_value(); }
std::error_code& Error() { return maybeEc.value(); }
const std::error_code& Error() const { return maybeEc.value(); }
operator std::error_code&() { return Error(); }
operator const std::error_code&() const { return Error(); }
private:
std::optional<std::error_code> maybeEc;
};
inline std::error_code ThrowErrno() {
return { errno, std::system_category() };
}
} // namespace dmtools