#pragma once #include #include #include template struct ErrorOr { private: using Variant = std::variant; 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(*maybeVariant); // No value. return false; } bool HasError() const { if(maybeVariant) return std::holds_alternative(*maybeVariant); // No error. Possibly in the default constructed state return false; } // ASSERT TODO T& Value() { return std::get(maybeVariant.value()); } const T& Value() const { return std::get(maybeVariant.value()); } operator T&() { return Value(); } operator const T&() { return Value(); } std::error_code& Error() { return std::get(maybeVariant.value()); } const std::error_code& Error() const { return std::get(maybeVariant.value()); } operator std::error_code&() { return Error(); } operator const std::error_code&() const { return Error(); } private: std::optional maybeVariant; }; template <> struct ErrorOr { 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 maybeEc; };