diff --git a/furlang/include/furlang/result.hpp b/furlang/include/furlang/result.hpp index 9dcdf76..e09c2d0 100644 --- a/furlang/include/furlang/result.hpp +++ b/furlang/include/furlang/result.hpp @@ -2,7 +2,9 @@ #define FURLANG_RESULT_HPP #include +#include #include +#include #include namespace furlang { @@ -43,6 +45,8 @@ public: const char* what() const noexcept override { return "bad result access"; } }; +struct error_tag {}; + /** * @brief Result. * @@ -51,7 +55,7 @@ public: * @tparam R Value type. * @tparam E Error type. */ -template +template class result { public: using value_type = std::remove_reference_t; /**< Value type. */ @@ -63,6 +67,10 @@ public: using error_reference = error_type&; /**< Error reference type. */ using error_const_reference = const error_type&; /**< Error const reference type. */ public: + template + result(const result& error) + : result(error_tag{}, error.error()) {} + /** * @brief Construct a new result. * @@ -82,7 +90,7 @@ public: * * @param args Variadic arguments to construct the value with. */ - template + template >> result(Args&&... args) { new (&m_value.result) value_type(std::forward(args)...); } @@ -92,7 +100,7 @@ public: * * @param error Error to copy. */ - explicit result(const error_type& error) + result(error_tag tag, const error_type& error) : m_error(true) { new (&m_value.error) error_type(error); } @@ -102,7 +110,7 @@ public: * * @param error Error to move. */ - explicit result(error_type&& error) + result(error_tag tag, error_type&& error) : m_error(true) { new (&m_value.error) error_type(std::move(error)); } @@ -166,6 +174,16 @@ public: } return *this; } +public: + template >> + static result ok(ResultFwd&& value) { + return { std::forward(value) }; + } + + template >> + static result error(ErrorFwd&& value) { + return { error_tag{}, std::forward(value) }; + } public: /** * @brief Checks if this result contains a value. @@ -364,6 +382,34 @@ private: bool m_error = false; }; +template +class result { +public: + using value_type = std::remove_reference_t; + using reference = value_type&; + using const_reference = const value_type&; +public: + result() = default; + + result(const value_type& value) + : m_error(true), m_value(value) {} + + result(value_type&& value) + : m_error(true), m_value(std::move(value)) {} + + template >> + result(Args&&... args) + : m_error(true), m_value(std::forward(args)...) {} +public: + bool has_value() const { return !m_error; } + bool has_error() const { return m_error; } + + const value_type& error() const { return *m_value; } +private: + std::optional m_value; + bool m_error = false; +}; + } // namespace furlang -#endif // FURLANG_RESULT_HPP \ No newline at end of file +#endif // FURLANG_RESULT_HPP