// Result type, similar to Rust Result
#pragma once
#include<any>#include<iostream>#include<stdexcept>#include<string>// custom exception(optional)
classResultExceptionfinal:publicstd::runtime_error{public:explicitResultException(conststd::string&message):std::runtime_error(message){}};template<typenameT,typenameE=std::string>classResult{private:// Using variant is actually better, but when T and E are of the same type, it can cause ambiguity.
// std::variant<T, E> data;
std::anyok_;std::anyerr_;public:// Construct a successful Result
staticResultOk(Tvalue){Resultresult;result.ok_=std::move(value);returnresult;}// Construct a wrong Result
staticResultErr(Eerror){Resultresult;result.err_=std::move(error);returnresult;}// Check if successful
[[nodiscard]]boolis_ok()const{returnok_.has_value();}// Check if error
[[nodiscard]]boolis_err()const{returnerr_.has_value();}// Get the successful value and throw an exception if it is an error
Tunwrap()const{if(is_err()){throwResultException("Unwrapped an Err value");}returnstd::any_cast<T>(ok_);}// Get the error value and throw an exception if successful
Eunwrap_err()const{if(is_ok()){throwResultException("Unwrapped_err on an Ok value");}returnstd::any_cast<E>(err_);}// Get values safely, provide default values
Tunwrap_or(Tdefault_value)const{returnis_ok()?std::any_cast<T>(ok_):default_value;}// Pattern matching style processing
template<typenameOkFunc,typenameErrFunc>automatch(OkFuncok_func,ErrFuncerr_func)const{if(is_ok()){returnok_func(std::any_cast<T>(ok_));}else{returnerr_func(std::any_cast<E>(err_));}}};
预览: