#pragma once #include "std/ensure.h" #include "std/string.h" #include "utils/move.h" #include "utils/new.h" 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) { m_storage.store_reference(other.m_storage.fetch_reference()); m_has_value = true; m_has_error = false; } Result(Result&& other) { m_storage.store_movable_reference(move(other.m_storage.fetch_reference())); m_has_value = true; m_has_error = false; } 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 release_value() { ensure(has_value()); T item = m_storage.fetch_reference(); m_has_value = false; return move(item); } private: struct Storage { unsigned char buffer[sizeof(T)]; T* fetch_ptr() { return (T*)buffer; } T& fetch_reference() { 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); } }; Storage m_storage; int m_error; bool m_has_error; bool m_has_value; };