Files
LXC/Common/modules/Result.h
2025-08-03 19:16:54 +01:00

122 lines
3.5 KiB
C++

#pragma once
#include <modules/OS.h>
#include <type_traits>
#include <cstdlib>
namespace LXC::Util
{
// Util function to stop the program //
inline void Stop()
{
// Only checks for a debugger when compiled in Debug mode //
#ifdef _DEBUG
// Triggers a breakpoint so the debugger can work out where the program exits //
if (IsDebuggerPresent())
DebugBreak();
#endif // _DEBUG
// Force exits the program //
std::exit(EXIT_FAILURE);
}
// Custom version of std::unexpected //
template<typename ErrorType> struct FunctionFail final
{
// Basic constructor to copy the error across //
explicit FunctionFail(ErrorType _err) : error(_err)
{
// Only checks for a debugger when compiled in Debug mode //
#ifdef _DEBUG
// Triggers a breakpoint when a debugger is attached as a function has failed //
if (IsDebuggerPresent())
DebugBreak();
#endif // _DEBUG
}
// Constructs the FunctionFail with the error itself //
template<typename... Args> requires std::constructible_from<ErrorType, Args...>
explicit FunctionFail(Args&&... args)
: error(std::forward<Args>(args)...)
{
// Only checks for a debugger when compiled in Debug mode //
#ifdef _DEBUG
// Triggers a breakpoint when a debugger is attached as a function has failed //
if (IsDebuggerPresent())
DebugBreak();
#endif // _DEBUG
}
const ErrorType error;
};
// Custom version of std::expected //
template<typename ResultType, typename ErrorType>
requires (!std::same_as<ResultType, bool>) // ResultType being bool causes issues with operator overloads
class ReturnVal final
{
public:
// Constructor for function sucess //
ReturnVal(const ResultType& result)
: m_Result(result), m_FunctionFailed(false)
{}
// Move constructor (for large objects) //
ReturnVal(ResultType&& result)
: m_Result(std::move(result)), m_FunctionFailed(false)
{}
// Constructor for function fail //
ReturnVal(FunctionFail<ErrorType> error)
: m_Error(error.error), m_FunctionFailed(true)
{}
// Destructor //
~ReturnVal() {};
// Different getters of the class //
inline bool Failed() const { return m_FunctionFailed; }
inline bool Suceeded() const { return !m_FunctionFailed; }
inline ResultType& Result()
{
if (Suceeded()) _LIKELY
return m_Result;
std::exit(EXIT_FAILURE);
}
inline ErrorType& Error()
{
if (Failed()) _LIKELY
return m_Error;
std::exit(EXIT_FAILURE);
}
// Operator overloads //
explicit operator bool() const { return !m_FunctionFailed; }
operator ResultType&() { return Result(); }
private:
// Union to hold either the result or the error //
union
{
ResultType m_Result;
ErrorType m_Error;
};
// Tracks what item is currently in the union //
bool m_FunctionFailed;
};
}