refactor(furlang): improve results

This commit is contained in:
2026-09-06 15:09:34 +02:00
parent 9bf4da4fd9
commit 35d7fc4970
+51 -5
View File
@@ -2,7 +2,9 @@
#define FURLANG_RESULT_HPP #define FURLANG_RESULT_HPP
#include <exception> #include <exception>
#include <optional>
#include <ostream> #include <ostream>
#include <type_traits>
#include <utility> #include <utility>
namespace furlang { namespace furlang {
@@ -43,6 +45,8 @@ public:
const char* what() const noexcept override { return "bad result access"; } const char* what() const noexcept override { return "bad result access"; }
}; };
struct error_tag {};
/** /**
* @brief Result. * @brief Result.
* *
@@ -51,7 +55,7 @@ public:
* @tparam R Value type. * @tparam R Value type.
* @tparam E Error type. * @tparam E Error type.
*/ */
template <typename R, typename E> template <typename E, typename R = void>
class result { class result {
public: public:
using value_type = std::remove_reference_t<R>; /**< Value type. */ using value_type = std::remove_reference_t<R>; /**< Value type. */
@@ -63,6 +67,10 @@ public:
using error_reference = error_type&; /**< Error reference type. */ using error_reference = error_type&; /**< Error reference type. */
using error_const_reference = const error_type&; /**< Error const reference type. */ using error_const_reference = const error_type&; /**< Error const reference type. */
public: public:
template <typename Other>
result(const result<E, Other>& error)
: result(error_tag{}, error.error()) {}
/** /**
* @brief Construct a new result. * @brief Construct a new result.
* *
@@ -82,7 +90,7 @@ public:
* *
* @param args Variadic arguments to construct the value with. * @param args Variadic arguments to construct the value with.
*/ */
template <typename... Args> template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
result(Args&&... args) { result(Args&&... args) {
new (&m_value.result) value_type(std::forward<Args>(args)...); new (&m_value.result) value_type(std::forward<Args>(args)...);
} }
@@ -92,7 +100,7 @@ public:
* *
* @param error Error to copy. * @param error Error to copy.
*/ */
explicit result(const error_type& error) result(error_tag tag, const error_type& error)
: m_error(true) { : m_error(true) {
new (&m_value.error) error_type(error); new (&m_value.error) error_type(error);
} }
@@ -102,7 +110,7 @@ public:
* *
* @param error Error to move. * @param error Error to move.
*/ */
explicit result(error_type&& error) result(error_tag tag, error_type&& error)
: m_error(true) { : m_error(true) {
new (&m_value.error) error_type(std::move(error)); new (&m_value.error) error_type(std::move(error));
} }
@@ -166,6 +174,16 @@ public:
} }
return *this; return *this;
} }
public:
template <typename ResultFwd, typename = std::enable_if_t<std::is_constructible_v<R, ResultFwd>>>
static result ok(ResultFwd&& value) {
return { std::forward<ResultFwd>(value) };
}
template <typename ErrorFwd, typename = std::enable_if_t<std::is_constructible_v<E, ErrorFwd>>>
static result error(ErrorFwd&& value) {
return { error_tag{}, std::forward<ErrorFwd>(value) };
}
public: public:
/** /**
* @brief Checks if this result contains a value. * @brief Checks if this result contains a value.
@@ -364,6 +382,34 @@ private:
bool m_error = false; bool m_error = false;
}; };
template <typename E>
class result<E, void> {
public:
using value_type = std::remove_reference_t<E>;
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 <typename... Args, typename = std::enable_if_t<std::is_constructible_v<value_type, Args...>>>
result(Args&&... args)
: m_error(true), m_value(std::forward<Args>(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<value_type> m_value;
bool m_error = false;
};
} // namespace furlang } // namespace furlang
#endif // FURLANG_RESULT_HPP #endif // FURLANG_RESULT_HPP