#pragma once #include #include #include 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 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 requires std::constructible_from explicit FunctionFail(Args&&... args) : error(std::forward(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 requires (!std::same_as) // 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 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 // 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; }; }