105 lines
2.3 KiB
C++
105 lines
2.3 KiB
C++
|
// 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
|