diff --git a/include/fcarouge/internal/format.hpp b/include/fcarouge/internal/format.hpp index 405bce16e..c6ffb1b6d 100644 --- a/include/fcarouge/internal/format.hpp +++ b/include/fcarouge/internal/format.hpp @@ -58,14 +58,16 @@ template , Char> { + using kalman = + fcarouge::kalman; + constexpr auto parse(std::basic_format_parse_context &parse_context) { return parse_context.begin(); } //! @todo P2585 may be useful in simplifying and standardizing the support. template - auto format(const fcarouge::kalman &filter, + auto format(const kalman &filter, std::basic_format_context &format_context) const -> OutputIt { format_context.advance_to( @@ -96,7 +98,9 @@ struct std::formatter< R"("q": {}, "r": {}, "s": {}, )", filter.q(), filter.r(), filter.s())); - if constexpr (requires { filter.u(); }) { + //! @todo Generalize out internal method concept when MSVC has better + //! if-constexpr-requires support. + if constexpr (fcarouge::internal::has_input_method) { format_context.advance_to( format_to(format_context.out(), R"("u": {}, )", filter.u())); } diff --git a/include/fcarouge/internal/kalman.tpp b/include/fcarouge/internal/kalman.tpp index 3b590587b..65e59d5d3 100644 --- a/include/fcarouge/internal/kalman.tpp +++ b/include/fcarouge/internal/kalman.tpp @@ -77,17 +77,19 @@ kalman::z() const template [[nodiscard("The returned control column vector U is unexpectedly " - "discarded.")]] inline constexpr auto + "discarded.")]] inline constexpr const auto & kalman::u() const - -> const input &requires(requires { filter.u; }) { return filter.u; } + requires(has_input) +{ + return filter.u; +} template [[nodiscard("The returned estimated covariance matrix P is unexpectedly " - "discarded.")]] inline constexpr auto kalman::p() - const -> const estimate_uncertainty & { + "discarded.")]] inline constexpr auto +kalman::p() const + -> const estimate_uncertainty & { return filter.p; } diff --git a/include/fcarouge/internal/utility.hpp b/include/fcarouge/internal/utility.hpp index 768b31093..2025562a3 100644 --- a/include/fcarouge/internal/utility.hpp +++ b/include/fcarouge/internal/utility.hpp @@ -52,6 +52,16 @@ concept algebraic = not arithmetic; template concept eigen = requires { typename Type::PlainMatrix; }; +template +concept has_input_member = requires(Filter filter) { filter.u; }; + +template +concept has_input_method = requires(Filter filter) { filter.u(); }; + +//! @todo Shorten when MSVC has better if-constexpr-requires support. +template +concept has_input = has_input_member || has_input_method; + struct empty { inline constexpr explicit empty([[maybe_unused]] auto &&...any) noexcept { // Constructs from anything for all initializations compatibility. diff --git a/include/fcarouge/kalman.hpp b/include/fcarouge/kalman.hpp index 51653a446..e314d34af 100644 --- a/include/fcarouge/kalman.hpp +++ b/include/fcarouge/kalman.hpp @@ -346,8 +346,8 @@ class kalman final { //! @return The last control column vector U. //! //! @complexity Constant. - inline constexpr auto u() const - -> const input &requires(requires { filter.u; }); + inline constexpr const auto &u() const + requires(has_input); //! @brief Returns the estimated covariance matrix P. //! diff --git a/include/fcarouge/utility.hpp b/include/fcarouge/utility.hpp index 066bc3791..9a6267aa8 100644 --- a/include/fcarouge/utility.hpp +++ b/include/fcarouge/utility.hpp @@ -69,6 +69,13 @@ concept algebraic = internal::algebraic; //! @details A third party Eigen3 algebraic concept. template concept eigen = internal::eigen; + +//! @brief Filter input support concept. +//! +//! @details The filter supports the input related functionality: `input` type +//! member and `u()` input method. +template +concept has_input = internal::has_input; //! @} //! @name Types