#pragma once #include #include #include struct Error { Error(int err) { error = err; } int error; }; template class Result { public: Result(const T& value) { m_storage.store_reference(value); m_has_value = true; m_has_error = false; } Result(T&& value) { m_storage.store_movable_reference(move(value)); m_has_value = true; m_has_error = false; } Result(const Result& other) { if (!other.m_has_error) { m_storage.store_reference(other.m_storage.fetch_reference()); m_has_value = true; m_has_error = false; } else { m_has_error = true; m_has_value = false; m_error = other.m_error; } } Result(Result&& other) { if (!other.m_has_error) { m_storage.store_movable_reference(move(other.m_storage.fetch_reference())); m_has_value = true; m_has_error = false; } else { m_has_error = true; m_has_value = false; m_error = other.m_error; } } Result(const Error& err) { m_error = err.error; m_has_error = true; m_has_value = false; } bool has_error() { return m_has_error; } bool has_value() { return m_has_value; } int error() { // ensure(has_error()); return m_error; } Error release_error() { // ensure(has_error()); return {m_error}; } T value() { // ensure(has_value()); return m_storage.fetch_reference(); } T value_or(T other) { if (has_value()) return m_storage.fetch_reference(); return other; } T release_value() { // ensure(has_value()); T item = m_storage.fetch_reference(); m_has_value = false; m_storage.destroy(); return move(item); } ~Result() { if (has_value()) m_storage.destroy(); } private: struct Storage { u8 buffer[sizeof(T)]; T* fetch_ptr() { return (T*)buffer; } T& fetch_reference() { return *fetch_ptr(); } const T* fetch_ptr() const { return (const T*)buffer; } const T& fetch_reference() const { return *fetch_ptr(); } void store_ptr(T* ptr) { new (buffer) T(*ptr); } void store_reference(const T& ref) { new (buffer) T(ref); } void store_movable_reference(T&& ref) { new (buffer) T(ref); } void destroy() { fetch_reference().~T(); } }; Storage m_storage; int m_error; bool m_has_error; bool m_has_value; }; template <> class Result { public: Result() { m_has_error = false; } Result(const Result& other) { m_has_error = other.m_has_error; m_error = other.m_error; } Result(Result&& other) { m_has_error = other.m_has_error; m_error = other.m_error; } Result(const Error& err) { m_error = err.error; m_has_error = true; } bool has_error() { return m_has_error; } bool has_value() { return !m_has_error; } int error() { // ensure(has_error()); return m_error; } Error release_error() { // ensure(has_error()); return {m_error}; } void value() { // ensure(has_value()); return; } void release_value() { // ensure(has_value()); return; } private: int m_error; bool m_has_error; }; // clang-format off #define err Error{0} // clang-format on