#pragma once #include "macro/class_copy_move.hpp" #include #include #include /// @brief The namespace containing generic constraint concept used varied in other modules. namespace yycc::constraint { /// @brief Function prototype used in Constraint for checking whether given value is valid. /// @details Analyze given value, and return true if value is legal, otherwise false. template using FnCheck = std::function; /// @brief Function prototype used in Constraint for clamping given value into a valid value. /// @details Analyze given value, return clamped value. template using FnClamp = std::function; /** * @brief The constraint applied to settings to limit its stored value. * @tparam T The data type this constraint need to be processed with. * @details * Constraint class contains various features: * \li Check: Check whether given value is in range. * \li Clamp: Clamp given value into valid value. * Every instances of Constraint can have some, or none of these features. * So it is essential to check whether instance has corresponding features before using it. */ template class Constraint { public: Constraint(FnCheck&& fn_check, FnClamp&& fn_clamp) : fn_check(std::move(fn_check)), fn_clamp(std::move(fn_clamp)) {} YYCC_DELETE_COPY(Constraint) YYCC_DEFAULT_MOVE(Constraint) /** * @brief Perform Check feature. * @param[in] value The valid for checking. * @return True if valid is okey, otherwise false. * @exception std::logic_error Raised if this feature is not supported. */ bool check(const T& value) const { if (!support_check()) { throw std::logic_error("this Constraint do not support check operation"); } else { return fn_check(value); } } /** * @brief Perform Clamp feature. * @param[in] value The valid for clamping. * @return The result after clamping. * @exception std::logic_error Raised if this feature is not supported. */ T clamp(const T& value) const { if (!support_clamp()) { throw std::logic_error("this Constraint do not support clamp operation"); } else { return fn_clamp(value); } } /// @brief Check whether this Constraint support Check feature. /// @return True if it support, otherwise false. bool support_check() const noexcept { return this->fn_check != nullptr; } /// @brief Check whether this Constraint support Clamp feature. /// @return True if it support, otherwise false. bool support_clamp() const noexcept { return this->fn_clamp != nullptr; } private: /// @brief Pointer to Check feature function. FnCheck fn_check; /// @brief Pointer to Clamp feature function. FnClamp fn_clamp; }; } // namespace yycc::core::constraint