diff --git a/luna/include/luna/Result.h b/luna/include/luna/Result.h index a923bff4..1b93b37e 100644 --- a/luna/include/luna/Result.h +++ b/luna/include/luna/Result.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -18,25 +19,22 @@ struct Error template class Result { public: - Result(const T& value) + Result(const T& value) : m_value(value) { - m_storage.store_reference(value); m_has_value = true; m_has_error = false; } - Result(T&& value) + Result(T&& value) : m_value(value) { - m_storage.store_movable_reference(move(value)); m_has_value = true; m_has_error = false; } - Result(const Result& other) + Result(const Result& other) : m_value(other.m_value) { if (!other.m_has_error) { - m_storage.store_reference(other.m_storage.fetch_reference()); m_has_value = true; m_has_error = false; } @@ -48,11 +46,10 @@ template class Result } } - Result(Result&& other) + Result(Result&& other) : m_value(other.m_value) { if (!other.m_has_error) { - m_storage.store_movable_reference(move(other.m_storage.fetch_reference())); m_has_value = true; m_has_error = false; } @@ -64,7 +61,7 @@ template class Result } } - Result(const Error& err) + Result(const Error& err) : m_value() { m_error = err.error; m_has_error = true; @@ -102,98 +99,39 @@ template class Result T value() { expect(has_value(), "Result::value() called on a Result that holds an error"); - return m_storage.fetch_reference(); + return m_value.value(); } T expect_value(const char* reason) { expect(has_value(), reason); - return m_storage.fetch_reference(); + return move(m_value.release_value()); } - T value_or(T other) + T value_or(const T& other) { - if (has_value()) return m_storage.fetch_reference(); - return other; + return m_value.value_or(other); } bool try_set_value(T& ref) { - if (!has_value()) return false; - ref = m_storage.fetch_reference(); - return true; + return m_value.try_set_value(ref); } T release_value() { expect(has_value(), "Result::release_value() called on a Result that holds an error"); - T item = m_storage.fetch_reference(); - m_has_value = false; - m_storage.destroy(); - return move(item); + return m_value.release_value(); } T expect_release_value(const char* reason) { expect(has_value(), reason); - T item = m_storage.fetch_reference(); - m_has_value = false; - m_storage.destroy(); - return move(item); - } - - ~Result() - { - if (has_value()) m_storage.destroy(); + return m_value.release_value(); } 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; + Option m_value; int m_error; bool m_has_error; bool m_has_value; @@ -289,6 +227,6 @@ template <> class Result #define TRY(expr) \ ({ \ auto _expr_rc = (expr); \ - if (_expr_rc.has_error()) return _expr_rc.release_error(); \ + if (!_expr_rc.has_value()) return _expr_rc.release_error(); \ _expr_rc.expect_release_value("sanity check failed: has_error() returned false, yet result has no value"); \ })