diff --git a/include/rfl/Result.hpp b/include/rfl/Result.hpp index adc52505..38e0c067 100644 --- a/include/rfl/Result.hpp +++ b/include/rfl/Result.hpp @@ -24,7 +24,7 @@ class Error { /// Constructs an error with a message (copy). /// @param _what The error message describing what went wrong Error(const std::string& _what) : what_(_what) {} - + /// Constructs an error with a message (move). /// @param _what The error message describing what went wrong (will be moved) Error(std::string&& _what) : what_(std::move(_what)) {} @@ -35,7 +35,7 @@ class Error { /// Copy constructor. /// @param e The error to copy from Error(const Error& e) = default; - + /// Move constructor. /// @param e The error to move from Error(Error&& e) noexcept = default; @@ -78,22 +78,37 @@ using Result = std::expected; template struct Unexpected { + /// Constructs an Unexpected object with the given error (perfect forwarding). + /// @param _err The error to store in this Unexpected object. Unexpected(E&& _err) : err_{std::forward(_err)} {} + /// Constructs an Unexpected object with the given error (copy). + /// @param _err The error to store in this Unexpected object (copy) Unexpected(const E& _err) : err_{_err} {} + /// Move constructor. + /// @param _other The Unexpected object to move from Unexpected(Unexpected&&) = default; + /// Copy constructor. + /// @param _other The Unexpected object to copy from Unexpected(const Unexpected&) = default; + /// Move assignment operator. + /// @param _other The Unexpected object to move from Unexpected& operator=(Unexpected&&) = default; + /// Copy assignment operator. + /// @param _other The Unexpected object to copy from Unexpected& operator=(const Unexpected&) = default; + /// Returns the error stored in this Unexpected object (const reference). const E& error() const& { return err_; } + /// Returns the error stored in this Unexpected object (rvalue reference). E&& error() && { return std::move(err_); } + /// Returns the error stored in this Unexpected object (lvalue reference). E& error() & { return err_; } private: @@ -101,6 +116,9 @@ struct Unexpected { }; /// The Result class is used for monadic error handling. +/// It can either contain a value of type T (indicating success) or an Error +/// (indicating failure). The class provides various methods for chaining +/// operations, transforming values, and handling errors in a functional style. template class Result { static_assert(!std::is_same(), "The result type cannot be Error."); @@ -108,31 +126,54 @@ class Result { using TOrErr = std::array; public: - // using Type = T; using value_type = T; using error_type = rfl::Error; - + /// @brief Constructs a successful Result holding a copy of the given value. + /// @param _val The value to copy into the Result. Result(const T& _val) : success_(true) { new (&get_t()) T(_val); } + /// @brief Constructs a successful Result by moving the given value. + /// @param _val The value to move into the Result. Result(T&& _val) noexcept : success_(true) { new (&get_t()) T(std::move(_val)); } + /// @brief Constructs an unsuccessful Result holding a copy of the given + /// error. + /// @param _err The Unexpected error to copy into the Result. Result(const Unexpected& _err) : success_(false) { new (&get_err()) Error(_err.error()); } + + /// @brief Constructs an unsuccessful Result by moving the given error. + /// @param _err The Unexpected error to move into the Result. Result(Unexpected&& _err) : success_(false) { new (&get_err()) Error(std::move(_err.error())); } + /// @brief Move constructor. Transfers ownership of the value or error from + /// another Result. + /// @param _other The Result to move from. After the move, _other is in a + /// valid but unspecified state. Result(Result&& _other) noexcept : success_(_other.success_) { move_from_other(_other); } + /// @brief Copy constructor for Result. + /// @param _other The other Result object to copy from. + /// @details Copies the success state and the contained value (if any) from + /// another Result of the same type. Result(const Result& _other) : success_(_other.success_) { copy_from_other(_other); } + /// @brief Move constructor template for Result from a convertible type. + /// @tparam U The type of the value contained in the other Result. + /// @param _other The other Result object to move from. + /// @details Constructs a Result by moving from a Result, where U is + /// convertible to T. The contained value is transformed and moved into the + /// new Result. If the other Result contains an error, + /// the error is propagated to this Result. template requires std::is_convertible_v Result(Result&& _other) : success_(_other && true) { @@ -141,6 +182,13 @@ class Result { move_from_other(temp); } + /// @brief Copy constructor template for Result from a convertible type. + /// @tparam U The type of the value contained in the other Result. + /// @param _other The other Result object to copy from. + /// @details Constructs a Result by copying from a Result, where U is + /// convertible to T. The contained value is transformed and copied into the + /// new Result. If the other Result contains an error, the error is propagated + /// to this Result. template requires std::is_convertible_v Result(const Result& _other) : success_(_other && true) { @@ -148,9 +196,24 @@ class Result { move_from_other(temp); } + /// @brief Destructor for Result. + /// @details Destroys the contained value (if any) and releases any resources + /// held by the Result. ~Result() { destroy(); } - /// Monadic operation - F must be a function of type T -> Result. + /// @brief Monadic operation that applies a function to the contained value if + /// the result is successful. + /// + /// This overload is for rvalue-qualified objects (i.e., temporaries or + /// moved-from objects). If the Result holds a value (success_), the provided + /// function F is invoked with the value (moved), and its result (which must + /// be another Result) is returned. If the Result holds an error, the error + /// is propagated to the returned Result. + /// + /// @tparam F A callable type accepting T and returning Result. + /// @param _f The function to apply to the contained value if present. + /// @return Result The result of applying _f to the value, or propagating + /// the error. template auto and_then(const F& _f) && { /// Result_U is expected to be of type Result. @@ -162,7 +225,19 @@ class Result { } } - /// Monadic operation - F must be a function of type T -> Result. + /// @brief Monadic operation that applies a function to the contained value if + /// the result is successful. + /// + /// This overload is for const lvalue-qualified objects (i.e., non-modifiable + /// references). If the Result holds a value (success_), the provided function + /// F is invoked with the value, and its result (which must be another + /// Result) is returned. If the Result holds an error, the error is + /// propagated to the returned Result. + /// + /// @tparam F A callable type accepting T and returning Result. + /// @param _f The function to apply to the contained value if present. + /// @return Result The result of applying _f to the value, or propagating + /// the error. template auto and_then(const F& _f) const& { /// Result_U is expected to be of type Result. @@ -189,7 +264,15 @@ class Result { /// undefined behavior, if the result contains an error. const T& operator*() const& noexcept { return get_t(); } - /// Assigns the underlying object. + /// @brief Copy assignment operator. + /// + /// Assigns the contents of another Result to this object. If the source + /// and destination are the same, no action is taken. Otherwise, destroys the + /// current contents, copies the success state, and copies the underlying + /// value or error from the other object. + /// + /// @param _other The Result object to copy from. + /// @return Reference to this Result. Result& operator=(const Result& _other) { if (this == &_other) { return *this; @@ -200,7 +283,15 @@ class Result { return *this; } - /// Assigns the underlying object. + /// @brief Move assignment operator. + /// + /// Assigns the contents of another Result to this object by moving. If the + /// source and destination are the same, no action is taken. Otherwise, + /// destroys the current contents, copies the success state, and moves the + /// underlying value or error from the other object. + /// + /// @param _other The Result object to move from. + /// @return Reference to this Result. Result& operator=(Result&& _other) noexcept { if (this == &_other) { return *this; @@ -211,6 +302,14 @@ class Result { return *this; } + /// @brief Move assignment from Unexpected. + /// + /// Assigns an error to this Result by moving from an Unexpected + /// object. Destroys the current contents, sets the state to failure, and + /// constructs the error in place. + /// + /// @param _err The Unexpected object to move the error from. + /// @return Reference to this Result. Result& operator=(Unexpected&& _err) noexcept { destroy(); success_ = false; @@ -218,6 +317,14 @@ class Result { return *this; } + /// @brief Copy assignment from Unexpected. + /// + /// Assigns an error to this Result by copying from an Unexpected + /// object. Destroys the current contents, sets the state to failure, and + /// constructs the error in place. + /// + /// @param _err The Unexpected object to copy the error from. + /// @return Reference to this Result. Result& operator=(const Unexpected& _err) noexcept { destroy(); success_ = false; @@ -225,7 +332,13 @@ class Result { return *this; } - /// Assigns the underlying object. + /// @brief Assigns the underlying object from another Result. + /// @tparam U The type of the value in the other Result. + /// @param _other The other Result to assign from. + /// @return Reference to this Result after assignment. + /// @details This assignment operator allows assigning from a Result where + /// U is convertible to T. It transforms the contained value (if any) from U + /// to T, destroys the current value, and moves the result. template requires std::is_convertible_v auto& operator=(const Result& _other) { @@ -237,8 +350,15 @@ class Result { return *this; } - /// Expects a function that takes of type Error -> Result and returns - /// Result. + /// @brief Applies a recovery function if the Result is an error (rvalue + /// overload). + /// @tparam F The type of the recovery function. + /// @param _f A function that takes an Error and returns a Result. + /// @return Result after applying the recovery function if this is an + /// error, otherwise the contained value. + /// @details This method is used for error recovery in a monadic style. If the + /// Result is successful, it returns the value. If it contains an error, it + /// calls the provided function with the error and returns its result. template Result or_else(const F& _f) && { if (success_) { @@ -248,8 +368,15 @@ class Result { } } - /// Expects a function that takes of type Error -> Result and returns - /// Result. + /// @brief Applies a recovery function if the Result is an error (const lvalue + /// overload). + /// @tparam F The type of the recovery function. + /// @param _f A function that takes an Error and returns a Result. + /// @return Result after applying the recovery function if this is an + /// error, otherwise the contained value. + /// @details This method is used for error recovery in a monadic style. If the + /// Result is successful, it returns the value. If it contains an error, it + /// calls the provided function with the error and returns its result. template Result or_else(const F& _f) const& { if (success_) { @@ -259,7 +386,15 @@ class Result { } } - /// Functor operation - F must be a function of type T -> U. + /// @brief Applies a transformation function to the contained value if + /// successful, moving the value. + /// @tparam F The type of the transformation function, must be callable as U + /// f(T). + /// @param _f The transformation function to apply to the contained value. + /// @return Result containing the transformed value if successful, + /// otherwise propagates the error. + /// @note This overload is for rvalue references (&&), so the contained value + /// is moved. template auto transform(const F& _f) && { /// Result_U is expected to be of type Result. @@ -271,7 +406,15 @@ class Result { } } - /// Functor operation - F must be a function of type T -> U. + /// @brief Applies a transformation function to the contained value if + /// successful, without moving the value. + /// @tparam F The type of the transformation function, must be callable as U + /// f(T). + /// @param _f The transformation function to apply to the contained value. + /// @return Result containing the transformed value if successful, + /// otherwise propagates the error. + /// @note This overload is for const lvalue references (const&), so the + /// contained value is not moved. template auto transform(const F& _f) const& { /// Result_U is expected to be of type Result. @@ -283,8 +426,18 @@ class Result { } } - /// Returns the value if the result does not contain an error, throws an - /// exceptions if not. Similar to .unwrap() in Rust. + /// @brief Returns the value if the result does not contain an error. + /// + /// This method is an rvalue-qualified overload, meaning it can only be called + /// on temporary objects. If the result is successful (i.e., contains a + /// value), it returns the value by rvalue reference, transferring ownership + /// using std::move. If the result contains an error, it throws a + /// std::runtime_error with the error message. This is similar to the + /// .unwrap() method in Rust, providing a convenient way to extract the value + /// or fail fast if an error is present. + /// + /// @return T&& The contained value, moved from the result object. + /// @throws std::runtime_error if the result contains an error. T&& value() && { if (success_) { return std::move(*this).get_t(); @@ -293,8 +446,17 @@ class Result { } } - /// Returns the value if the result does not contain an error, throws an - /// exceptions if not. Similar to .unwrap() in Rust. + /// @brief Returns the value if the result does not contain an error. + /// + /// This method is an lvalue-qualified overload, meaning it can only be called + /// on non-temporary objects. If the result is successful (i.e., contains a + /// value), it returns the value by reference. If the result contains an + /// error, it throws a std::runtime_error with the error message. This method + /// is similar to .unwrap() in Rust, allowing safe extraction of the value or + /// exception-based error handling. + /// + /// @return T& Reference to the contained value. + /// @throws std::runtime_error if the result contains an error. T& value() & { if (success_) { return get_t(); @@ -303,8 +465,17 @@ class Result { } } - /// Returns the value if the result does not contain an error, throws an - /// exceptions if not. Similar to .unwrap() in Rust. + /// @brief Returns the value if the result does not contain an error. + /// + /// This method is a const lvalue-qualified overload, meaning it can only be + /// called on const, non-temporary objects. If the result is successful (i.e., + /// contains a value), it returns a const reference to the value. If the + /// result contains an error, it throws a std::runtime_error with the error + /// message. This method is similar to .unwrap() in Rust, providing + /// exception-based error handling for const objects. + /// + /// @return const T& Const reference to the contained value. + /// @throws std::runtime_error if the result contains an error. const T& value() const& { if (success_) { return get_t(); @@ -313,7 +484,14 @@ class Result { } } - /// Returns the value or a default. + /// @brief Returns the contained value if present, otherwise returns the + /// provided default value. + /// @param _default The value to return if the Result does not contain a + /// value. + /// @return The contained value if present, otherwise the provided default + /// value. + /// @note This overload is for rvalue-qualified objects and moves the + /// contained value. T value_or(T&& _default) && noexcept { if (success_) { return std::move(*this).get_t(); @@ -322,7 +500,14 @@ class Result { } } - /// Returns the value or a default. + /// @brief Returns the contained value if present, otherwise returns the + /// provided default value. + /// @param _default The value to return if the Expected does not contain a + /// value. + /// @return The contained value if present, otherwise the provided default + /// value. + /// @note This overload is for const lvalue-qualified objects and copies the + /// contained value. T value_or(const T& _default) const& noexcept { if (success_) { return get_t(); @@ -331,6 +516,14 @@ class Result { } } + /// @brief Returns the contained error if present, otherwise returns the + /// provided default error. + /// @tparam G The type of the default error to return if no error is present. + /// @param _default The error to return if the Expected contains a value. + /// @return The contained error if present, otherwise the provided default + /// error. + /// @note This overload is for rvalue-qualified objects and moves the + /// contained error. template rfl::Error error_or(G&& _default) && { if (success_) { @@ -343,6 +536,15 @@ class Result { // As specified by the standard : // https://en.cppreference.com/w/cpp/utility/expected // Observers + + /// @brief Returns the contained error if present, otherwise returns the + /// provided default error. + /// @tparam G The type of the default error to return if no error is present. + /// @param _default The error to return if the Expected contains a value. + /// @return The contained error if present, otherwise the provided default + /// error. + /// @note This overload is for const lvalue-qualified objects and copies the + /// contained error. template rfl::Error error_or(G&& _default) const& { if (success_) { @@ -352,27 +554,64 @@ class Result { } } + /// @brief Checks whether the Expected contains a value. + /// @return true if the Expected contains a value, false if it contains an + /// error. bool has_value() const noexcept { return success_; } + /// @brief Returns the contained error, moving it if present. + /// @return The contained error, moved from the Expected. + /// @throws std::runtime_error if the Expected contains a value instead of an + /// error. Error&& error() && { if (success_) throw std::runtime_error("Expected does not contain value"); return std::move(*this).get_err(); } + /// @brief Returns the contained error by reference. + /// @return Reference to the contained error. + /// @throws std::runtime_error if the Expected contains a value instead of an + /// error. Error& error() & { if (success_) throw std::runtime_error("Expected does not contain value"); return get_err(); } + /// @brief Returns the contained error by const reference. + /// @return Const reference to the contained error. + /// @throws std::runtime_error if the Expected contains a value instead of an + /// error. const Error& error() const& { if (success_) throw std::runtime_error("Expected does not contain value"); return get_err(); } + /// @brief Provides pointer-like access to the contained value. + /// @return Pointer to the contained value of type T. T* operator->() noexcept { return &get_t(); } + /// @brief Provides pointer-like access to the contained value (const + /// overload). + /// @return Const pointer to the contained value of type T. const T* operator->() const noexcept { return &get_t(); } + /** + * @brief Transforms the error contained in this Result using the provided + * function, if there is an error. + * + * This method is an rvalue overload and allows the caller to provide a + * function that takes an rfl::Error and returns a new rfl::Error. If this + * Result does not contain a value (i.e., it contains an error), the error is + * transformed using the provided function and a new Result is returned + * containing the transformed error. If this Result contains a value, the + * value is moved into a new Result and returned as-is. + * + * @tparam F A callable type that takes an rfl::Error and returns an + * rfl::Error. + * @param f The function to apply to the error if present. + * @return A new rfl::Result containing either the transformed error or the + * original value. + */ template rfl::Result transform_error(F&& f) && { static_assert( @@ -385,6 +624,23 @@ class Result { } } + /** + * @brief Transforms the error contained in this Result using the provided + * function, if there is an error (const lvalue overload). + * + * This method is a const lvalue overload and allows the caller to provide a + * function that takes an rfl::Error and returns a new rfl::Error. If this + * Result does not contain a value (i.e., it contains an error), the error is + * transformed using the provided function and a new Result is returned + * containing the transformed error. If this Result contains a value, the + * value is copied into a new Result and returned as-is. + * + * @tparam F A callable type that takes an rfl::Error and returns an + * rfl::Error. + * @param f The function to apply to the error if present. + * @return A new rfl::Result containing either the transformed error or the + * original value. + */ template rfl::Result transform_error(F&& f) const& { static_assert( @@ -398,6 +654,10 @@ class Result { } private: + /// @brief Copies the value or error from another Result instance. + /// @param _other The other Result to copy from. + /// @details If this Result holds a value, constructs a new T from the other's + /// value. Otherwise, constructs a new Error from the other's error. void copy_from_other(const Result& _other) { if (success_) { new (&get_t()) T(_other.get_t()); @@ -406,6 +666,9 @@ class Result { } } + /// @brief Destroys the contained value or error. + /// @details If this Result holds a value and T is destructible, calls the + /// destructor for T. Otherwise, calls the destructor for Error. void destroy() { if (success_) { if constexpr (std::is_destructible_v >) { @@ -416,30 +679,59 @@ class Result { } } + /// @brief Retrieves the contained value as an rvalue reference. + /// @return Rvalue reference to the contained T. + /// @note Only call if this Result holds a value. T&& get_t() && noexcept { return std::move(*std::launder(reinterpret_cast(t_or_err_.data()))); } + /// @brief Retrieves the contained value as an lvalue reference. + /// @return Lvalue reference to the contained T. + /// @note Only call if this Result holds a value. T& get_t() & noexcept { return *std::launder(reinterpret_cast(t_or_err_.data())); } + /// @brief Retrieves the contained value as a const lvalue reference. + /// @return Const lvalue reference to the contained T. + /// @note Only call if this Result holds a value. const T& get_t() const& noexcept { return *std::launder(reinterpret_cast(t_or_err_.data())); } + /// @brief Retrieves the contained error as an rvalue reference. + /// @return Rvalue reference to the contained Error. + /// @note Only call if this Result holds an error. Error&& get_err() && noexcept { return std::move(*std::launder(reinterpret_cast(t_or_err_.data()))); } + /// @brief Retrieves the contained error as an lvalue reference. + /// @return Lvalue reference to the contained Error. + /// @note Only call if this Result holds an error. Error& get_err() & noexcept { return *std::launder(reinterpret_cast(t_or_err_.data())); } + /// @brief Retrieves the contained error as a const lvalue reference. + /// @return Const lvalue reference to the contained Error. + /// @note Only call if this Result holds an error. const Error& get_err() const& noexcept { return *std::launder(reinterpret_cast(t_or_err_.data())); } + /// @brief Moves the contents from another Result instance. + /// + /// This method transfers ownership of the value or error from the given + /// Result reference (_other) into this instance. If this Result holds a + /// successful value (success_ is true), it move-constructs the value of type + /// T from _other into this instance. Otherwise, it move-constructs the Error + /// from _other. This operation does not throw exceptions. + /// + /// @param _other Reference to another Result to move from. + /// @note After this operation, the state of _other is valid but unspecified. + /// @note This function is noexcept and should not throw exceptions. void move_from_other(Result& _other) noexcept { if (success_) { new (&get_t()) T(std::move(_other.get_t())); @@ -447,6 +739,7 @@ class Result { new (&get_err()) Error(std::move(_other.get_err())); } } + /// Signifies whether this was a success. bool success_; @@ -476,16 +769,30 @@ inline Unexpected error(const Error& _err) { template <> class std::bad_expected_access : public bad_expected_access { public: + /// @brief Constructs a bad_expected_access exception with the given error. + /// @param er The rfl::Error object to store in this exception. explicit constexpr bad_expected_access(rfl::Error er) : err_(std::move(er)) {} + /// @brief Returns a C-string describing the error. + /// @return A pointer to a null-terminated string with the error message. + /// @note Overrides std::exception::what(). The string is owned by the + /// underlying rfl::Error. const char* what() const noexcept override { return err_.what().c_str(); } + /// @brief Returns a reference to the contained error object. + /// @return Reference to the stored rfl::Error. [[nodiscard]] rfl::Error& error() & noexcept { return err_; } + /// @brief Returns a const reference to the contained error object. + /// @return Const reference to the stored rfl::Error. [[nodiscard]] const rfl::Error& error() const& noexcept { return err_; } + /// @brief Moves and returns the contained error object. + /// @return Rvalue reference to the stored rfl::Error. [[nodiscard]] rfl::Error&& error() && noexcept { return std::move(err_); } + /// @brief Moves and returns the contained error object from a const rvalue. + /// @return Const rvalue reference to the stored rfl::Error. [[nodiscard]] const rfl::Error&& error() const&& noexcept { return std::move(err_); } diff --git a/include/rfl/Short.hpp b/include/rfl/Short.hpp index 46d6e708..07f0b94d 100644 --- a/include/rfl/Short.hpp +++ b/include/rfl/Short.hpp @@ -21,69 +21,113 @@ struct Short { static_assert(_name.length == 1, "Short name must be exactly one character."); - Short() requires std::is_default_constructible_v + /// @brief Default constructor. + /// @details Constructs the underlying value using its default constructor. + /// @requires Type must be default constructible. + Short() + requires std::is_default_constructible_v : value_(Type()) {} + /// @brief Constructs the Short wrapper from a const reference to the + /// underlying value. + /// @param _value The value to assign to the underlying field. Short(const Type& _value) : value_(_value) {} + /// @brief Constructs the Short wrapper by moving the underlying value. + /// @param _value The value to move into the underlying field. Short(Type&& _value) noexcept : value_(std::move(_value)) {} + /// @brief Move constructor. + /// @param _field The Short field to move from. Short(Short<_name, T>&& _field) noexcept = default; + /// @brief Copy constructor. + /// @param _field The Short field to copy from. Short(const Short<_name, T>& _field) = default; + /// @brief Constructs from another Short with a convertible underlying type. + /// @tparam U The type of the other Short's underlying value. + /// @param _field The other Short field to copy from. template Short(const Short<_name, U>& _field) : value_(_field.get()) {} + /// @brief Move constructs from another Short with a convertible underlying + /// type. + /// @tparam U The type of the other Short's underlying value. + /// @param _field The other Short field to move from. template Short(Short<_name, U>&& _field) : value_(std::move(_field.value_)) {} + /// @brief Constructs from a value convertible to the underlying type. + /// @tparam U The type of the value. + /// @param _value The value to assign. template requires std::is_convertible_v Short(const U& _value) : value_(_value) {} + /// @brief Move constructs from a value convertible to the underlying type. + /// @tparam U The type of the value. + /// @param _value The value to move. template requires std::is_convertible_v Short(U&& _value) noexcept : value_(std::forward(_value)) {} - /// Assigns the underlying object to its default value. + /// @brief Constructs the underlying object to its default value using Default + /// tag. + /// @tparam U The type to default construct (defaults to Type). + /// @param unused Default tag. template requires std::is_default_constructible_v Short(const Default&) : value_(Type()) {} + /// @brief Destructor. + /// @details Defaulted destructor for Short. ~Short() = default; - /// Returns the underlying object. + /// @brief Returns a const reference to the underlying object. + /// @return Const reference to the underlying value. const Type& get() const noexcept { return value_; } - /// Returns the underlying object. + /// @brief Returns a reference to the underlying object. + /// @return Reference to the underlying value. Type& get() noexcept { return value_; } - /// Returns the underlying object. + /// @brief Dereference operator. + /// @return Reference to the underlying value. Type& operator*() noexcept { return value_; } - /// Returns the underlying object. + /// @brief Dereference operator (const). + /// @return Const reference to the underlying value. const Type& operator*() const noexcept { return value_; } - /// Returns the underlying object. + /// @brief Function call operator. + /// @return Reference to the underlying value. Type& operator()() noexcept { return value_; } - /// Returns the underlying object. + /// @brief Function call operator (const). + /// @return Const reference to the underlying value. const Type& operator()() const noexcept { return value_; } - /// Assigns the underlying object. + /// @brief Assigns a new value to the underlying object. + /// @param _value The value to assign. + /// @return Reference to this Short. auto& operator=(const Type& _value) { value_ = _value; return *this; } - /// Assigns the underlying object. + /// @brief Move-assigns a new value to the underlying object. + /// @param _value The value to move. + /// @return Reference to this Short. auto& operator=(Type&& _value) noexcept { value_ = std::move(_value); return *this; } - /// Assigns the underlying object. + /// @brief Assigns a value convertible to the underlying type. + /// @tparam U The type of the value. + /// @param _value The value to assign. + /// @return Reference to this Short. template requires std::is_convertible_v auto& operator=(const U& _value) { @@ -91,7 +135,11 @@ struct Short { return *this; } - /// Assigns the underlying object to its default value. + /// @brief Assigns the underlying object to its default value using Default + /// tag. + /// @tparam U The type to default construct (defaults to Type). + /// @param unused Default tag. + /// @return Reference to this Short. template requires std::is_default_constructible_v auto& operator=(const Default&) { @@ -99,36 +147,50 @@ struct Short { return *this; } - /// Assigns the underlying object. + /// @brief Copy assignment operator. + /// @param _field The Short field to copy from. + /// @return Reference to this Short. Short<_name, T>& operator=(const Short<_name, T>& _field) = default; - /// Assigns the underlying object. + /// @brief Move assignment operator. + /// @param _field The Short field to move from. + /// @return Reference to this Short. Short<_name, T>& operator=(Short<_name, T>&& _field) = default; - /// Assigns the underlying object. + /// @brief Assigns from another Short with a convertible underlying type. + /// @tparam U The type of the other Short's underlying value. + /// @param _field The other Short field to copy from. + /// @return Reference to this Short. template auto& operator=(const Short<_name, U>& _field) { value_ = _field.get(); return *this; } - /// Assigns the underlying object. + /// @brief Move-assigns from another Short with a convertible underlying type. + /// @tparam U The type of the other Short's underlying value. + /// @param _field The other Short field to move from. + /// @return Reference to this Short. template auto& operator=(Short<_name, U>&& _field) { value_ = std::move(_field.value_); return *this; } - /// Assigns the underlying object. + /// @brief Sets the underlying object to a new value. + /// @param _value The value to assign. void set(const Type& _value) { value_ = _value; } - /// Assigns the underlying object. + /// @brief Sets the underlying object to a new value by moving. + /// @param _value The value to move. void set(Type&& _value) { value_ = std::move(_value); } - /// Returns the underlying object. + /// @brief Returns a reference to the underlying value. + /// @return Reference to the underlying value. Type& value() noexcept { return value_; } - /// Returns the underlying object. + /// @brief Returns a const reference to the underlying value. + /// @return Const reference to the underlying value. const Type& value() const noexcept { return value_; } /// The underlying value.