docs: document result

This commit is contained in:
2026-06-02 13:16:55 +02:00
parent 7ac994511c
commit fd98474a86
+172 -8
View File
@@ -6,45 +6,101 @@
namespace furlang { namespace furlang {
/**
* @brief Bad result access exception.
*/
class bad_result_access : public std::exception { class bad_result_access : public std::exception {
public: public:
bad_result_access() = default; bad_result_access() = default;
~bad_result_access() override = default; ~bad_result_access() override = default;
/**
* @brief Move constructor.
*/
bad_result_access(bad_result_access&&) noexcept = default; bad_result_access(bad_result_access&&) noexcept = default;
/**
* @brief Move constructor.
*/
bad_result_access& operator=(bad_result_access&&) noexcept = default; bad_result_access& operator=(bad_result_access&&) noexcept = default;
/**
* @brief Copy constructor.
*/
bad_result_access(const bad_result_access&) = default; bad_result_access(const bad_result_access&) = default;
/**
* @brief Copy constructor.
*/
bad_result_access& operator=(const bad_result_access&) = default; bad_result_access& operator=(const bad_result_access&) = default;
public: public:
/**
* @brief Returns a C-style string describing the cause of the error.
*
* @return The cause of the error.
*/
const char* what() const noexcept override { return "bad result access"; } const char* what() const noexcept override { return "bad result access"; }
}; };
/**
* @brief Result.
*
* Result stores either value or error.
*
* @tparam R Value type.
* @tparam E Error type.
*/
template <typename R, typename E> template <typename R, typename E>
class result { class result {
public: public:
using value_type = std::remove_reference_t<R>; using value_type = std::remove_reference_t<R>; /**< Value type. */
using value_reference = value_type&; using value_reference = value_type&; /**< Value reference type. */
using value_const_reference = const value_type&; using value_const_reference = const value_type&; /**< Value const reference type. */
using value_pointer = value_type*; using value_pointer = value_type*; /**< Value pointer type. */
using value_const_pointer = const value_type*; using value_const_pointer = const value_type*; /**< Value const pointer type. */
using error_type = std::remove_reference_t<E>; using error_type = std::remove_reference_t<E>; /**< Error type. */
using error_reference = error_type&; using error_reference = error_type&; /**< Error reference type. */
using error_const_reference = const error_type&; using error_const_reference = const error_type&; /**< Error const reference type. */
public: public:
/**
* @brief Construct a new result.
*
* @param value Value to copy.
*/
result(const value_type& value) { new (&m_value.result) value_type(value); } result(const value_type& value) { new (&m_value.result) value_type(value); }
/**
* @brief Construct a new result.
*
* @param value Value to move.
*/
result(value_type&& value) { new (&m_value.result) value_type(std::move(value)); } result(value_type&& value) { new (&m_value.result) value_type(std::move(value)); }
/**
* @brief Construct a new result.
*
* @param args Variadic arguments to construct the value with.
*/
template <typename... Args> template <typename... 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)...);
} }
/**
* @brief Construct a new error result.
*
* @param error Error to copy.
*/
explicit result(const error_type& error) explicit result(const error_type& error)
: m_error(true) { : m_error(true) {
new (&m_value.error) error_type(error); new (&m_value.error) error_type(error);
} }
/**
* @brief Construct a new error result.
*
* @param error Error to move.
*/
explicit result(error_type&& error) explicit result(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));
@@ -58,6 +114,9 @@ public:
} }
} }
/**
* @brief Move constructor.
*/
result(result&& other) noexcept result(result&& other) noexcept
: m_error(other.m_error) { : m_error(other.m_error) {
if (m_error) { if (m_error) {
@@ -67,6 +126,9 @@ public:
} }
} }
/**
* @brief Move constructor.
*/
result& operator=(result&& other) noexcept { result& operator=(result&& other) noexcept {
if (this == &other) return *this; if (this == &other) return *this;
m_error = other.m_error; m_error = other.m_error;
@@ -78,6 +140,9 @@ public:
return *this; return *this;
} }
/**
* @brief Copy constructor.
*/
result(const result& other) result(const result& other)
: m_error(other.m_error) { : m_error(other.m_error) {
if (m_error) { if (m_error) {
@@ -87,6 +152,9 @@ public:
} }
} }
/**
* @brief Copy constructor.
*/
result& operator=(const result& other) { result& operator=(const result& other) {
if (this == &other) return *this; if (this == &other) return *this;
m_error = other.m_error; m_error = other.m_error;
@@ -98,60 +166,156 @@ public:
return *this; return *this;
} }
public: public:
/**
* @brief Checks if this result contains a value.
*
* @return true if contains a value.
*/
operator bool() const { return !m_error; } operator bool() const { return !m_error; }
/**
* @brief Checks if this result contains an error.
*
* @return true if contains an error.
*/
bool operator!() const { return m_error; } bool operator!() const { return m_error; }
/**
* @brief Compares two results for equality.
*
* @param rhs Result to compare against.
* @return true if the results are equal.
*/
bool operator==(const result& rhs) const { bool operator==(const result& rhs) const {
return m_error == rhs.m_error && m_error ? m_value.error == rhs.m_value.error return m_error == rhs.m_error && m_error ? m_value.error == rhs.m_value.error
: m_value.result == rhs.m_value.result; : m_value.result == rhs.m_value.result;
} }
/**
* @brief Compares two results for inequality.
*
* @param rhs Result to compare against.
* @return true if the results are not equal.
*/
bool operator!=(const result& rhs) const { return !this->operator==(rhs); } bool operator!=(const result& rhs) const { return !this->operator==(rhs); }
/**
* @brief Returns a reference to value.
*
* @return Reference to the value.
*/
value_reference operator*() { return value(); } value_reference operator*() { return value(); }
/**
* @brief Returns a reference to value.
*
* @return Const reference to the value.
*/
value_const_reference operator*() const { return value(); } value_const_reference operator*() const { return value(); }
/**
* @brief Returns a pointer to value.
*
* @return Pointer to the value.
*/
value_pointer operator->() { return &value(); } value_pointer operator->() { return &value(); }
/**
* @brief Returns a pointer to value.
*
* @return Const pointer to the value.
*/
value_const_pointer operator->() const { return &value(); } value_const_pointer operator->() const { return &value(); }
public: public:
/**
* @brief Checks if this result has a value.
*
* @return true if has a value.
*/
bool has_value() const { return !m_error; } bool has_value() const { return !m_error; }
/**
* @brief Checks if this result has an error.
*
* @return true if has an error.
*/
bool has_error() const { return m_error; } bool has_error() const { return m_error; }
/**
* @brief Returns a reference to value.
*
* @return Reference to the value.
*/
value_reference value() { value_reference value() {
if (m_error) throw bad_result_access(); if (m_error) throw bad_result_access();
return m_value.result; return m_value.result;
} }
/**
* @brief Returns a reference to value.
*
* @return Const reference to the value.
*/
value_const_reference value() const { value_const_reference value() const {
if (m_error) throw bad_result_access(); if (m_error) throw bad_result_access();
return m_value.result; return m_value.result;
} }
/**
* @brief Returns a reference to error.
*
* @return Reference to the error.
*/
error_reference error() { error_reference error() {
if (!m_error) throw bad_result_access(); if (!m_error) throw bad_result_access();
return m_value.error; return m_value.error;
} }
/**
* @brief Returns a reference to error.
*
* @return Const reference to the error.
*/
error_const_reference error() const { error_const_reference error() const {
if (!m_error) throw bad_result_access(); if (!m_error) throw bad_result_access();
return m_value.error; return m_value.error;
} }
public: public:
/**
* @brief Sets this results value.
*
* @param value Value to copy.
*/
void set_value(const value_type& value) { void set_value(const value_type& value) {
if (m_error) m_value.error.~error_type(); if (m_error) m_value.error.~error_type();
new (&m_value.result) value_type(value); new (&m_value.result) value_type(value);
} }
/**
* @brief Sets this results value.
*
* @param value Value to move.
*/
void set_value(value_type&& value) { void set_value(value_type&& value) {
if (m_error) m_value.error.~error_type(); if (m_error) m_value.error.~error_type();
new (&m_value.result) value_type(std::move(value)); new (&m_value.result) value_type(std::move(value));
} }
/**
* @brief Sets this results error.
*
* @param error Error to copy.
*/
void set_error(const error_type& error) { void set_error(const error_type& error) {
if (!m_error) m_value.result.~value_type(); if (!m_error) m_value.result.~value_type();
new (&m_value.error) error_type(error); new (&m_value.error) error_type(error);
} }
/**
* @brief Sets this results error.
*
* @param error Error to move.
*/
void set_error(error_type&& error) { void set_error(error_type&& error) {
if (!m_error) m_value.result.~value_type(); if (!m_error) m_value.result.~value_type();
new (&m_value.error) error_type(std::move(error)); new (&m_value.error) error_type(std::move(error));