#pragma once #include #include #include namespace core { /** * @brief Контейнер результата выполнения операции. * * BasicResult хранит одно из двух состояний: * - успешный результат типа T; * - ошибку типа E. * * Создание объекта возможно только через фабричные методы: * Success() и Failure(), что делает намерение вызова явным. * * @tparam T Тип успешного результата. * @tparam E Тип ошибки. * * @note Копирование запрещено. * Объект поддерживает только перемещение. */ template class [[nodiscard]] BasicResult { public: /** * @brief Создает успешный результат. * * @param value Значение успешного результата. * * @return Объект BasicResult в состоянии успеха. */ static BasicResult Success(T value) { return BasicResult(SuccessTag{}, std::move(value)); } /** * @brief Создает результат с ошибкой. * * @param error Значение ошибки. * * @return Объект BasicResult в состоянии ошибки. */ static BasicResult Failure(E error) { return BasicResult(FailureTag{}, std::move(error)); } /** * @brief Запрещает копирование. */ BasicResult(const BasicResult &) = delete; /** * @brief Запрещает копирующее присваивание. */ BasicResult &operator=(const BasicResult &) = delete; /** * @brief Разрешает перемещение. */ BasicResult(BasicResult &&) noexcept = default; /** * @brief Разрешает перемещающее присваивание. */ BasicResult &operator=(BasicResult &&) noexcept = default; /** * @brief Проверяет успешность результата. * * @return true, если результат содержит значение T. * @return false, если результат содержит ошибку E. */ [[nodiscard]] bool isSuccess() const { return data_.index() == 0; } /** * @brief Проверяет наличие ошибки в результате. * * @return true, если результат содержит ошибку E. * @return false, если результат содержит значение T. */ [[nodiscard]] bool isFailure() const { return data_.index() == 1; } /** * @brief Возвращает значение успешного результата. * * @return Константная ссылка на значение типа T. * * @warning Метод должен вызываться только после проверки * isSuccess(). * * @throws std::bad_variant_access * если объект содержит ошибку. */ [[nodiscard]] const T &getValue() const { return std::get<0>(data_); } /** * @brief Возвращает изменяемое значение успешного результата. * * @return Ссылка на значение типа T. * * @warning Метод должен вызываться только после проверки * isSuccess(). */ [[nodiscard]] T &getValue() { return std::get<0>(data_); } /** * @brief Возвращает ошибку результата. * * @return Константная ссылка на ошибку типа E. * * @warning Метод должен вызываться только если isSuccess() * возвращает false. * * @throws std::bad_variant_access * если объект содержит успешный результат. */ [[nodiscard]] const E &getError() const { return std::get<1>(data_); } /** * @brief Возвращает изменяемую ошибку результата. * * @return Ссылка на ошибку типа E. * * @warning Метод должен вызываться только если isSuccess() * возвращает false. */ [[nodiscard]] E &getError() { return std::get<1>(data_); } private: /** * @brief Вспомогательный тип для выбора конструктора успеха. */ struct SuccessTag {}; /** * @brief Вспомогательный тип для выбора конструктора ошибки. */ struct FailureTag {}; /** * @brief Внутренний конструктор успешного результата. * * Доступен только через Success(). */ explicit BasicResult(SuccessTag, T value) : data_(std::in_place_index<0>, std::move(value)) {} /** * @brief Внутренний конструктор результата с ошибкой. * * Доступен только через Failure(). */ explicit BasicResult(FailureTag, E error) : data_(std::in_place_index<1>, std::move(error)) {} private: /** * @brief Хранилище результата. * * Первый вариант — успешное значение T. * Второй вариант — ошибка E. */ std::variant data_; }; /** * @brief Результат операции с текстовой ошибкой. * * Упрощенный вариант BasicResult, где ошибка всегда представлена * строкой std::string. * * Пример: * * @code * core::Result load() * { * return core::Result::Success(100); * } * * core::Result parse() * { * return core::Result::Failure("Invalid format"); * } * @endcode * * @tparam T Тип успешного результата. */ template using Result = BasicResult; /** * @brief Статус выполнения операции. * * Используется для операций, где важно только состояние: * успех или сообщение об ошибке. * * Пример: * * @code * core::Status save() * { * return core::Status::Success(true); * } * @endcode */ using Status = Result; } // namespace core