From b8b6c130c2505039c1252edac9661b70cd1e2574 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Sun, 24 Nov 2024 19:46:42 +0100 Subject: [PATCH] refactor: CPOs refactored to be more constrained --- .../mp-units/framework/customization_points.h | 106 ---------------- .../framework/representation_concepts.h | 114 +++++++++++++++++- 2 files changed, 110 insertions(+), 110 deletions(-) diff --git a/src/core/include/mp-units/framework/customization_points.h b/src/core/include/mp-units/framework/customization_points.h index 43f8cfff2..29dcda6ab 100644 --- a/src/core/include/mp-units/framework/customization_points.h +++ b/src/core/include/mp-units/framework/customization_points.h @@ -105,112 +105,6 @@ constexpr bool is_vector = false; template constexpr bool is_tensor = false; -MP_UNITS_EXPORT_END - -namespace detail::norm_impl { - -void norm() = delete; // poison pill - -struct norm_t { - template - [[nodiscard]] constexpr auto operator()(const T& vec) const - { - if constexpr (requires { vec.norm(); }) - return vec.norm(); - else if constexpr (requires { norm(vec); }) - return norm(vec); - else if constexpr (requires { vec.magnitude(); }) - return vec.magnitude(); - else if constexpr (requires { magnitude(vec); }) - return magnitude(vec); - // TODO Is it a good idea to enable fundamental types to represent vector quantities? - // else if constexpr (is_scalar) - // return std::abs(vec); - } -}; - -} // namespace detail::norm_impl - -inline namespace cpo { - -MP_UNITS_EXPORT inline constexpr ::mp_units::detail::norm_impl::norm_t norm; - -} - -namespace detail::real_impl { - -void real() = delete; // poison pill - -struct real_t { - template - [[nodiscard]] constexpr auto operator()(const T& clx) const - { - if constexpr (requires { clx.real(); }) - return clx.real(); - else if constexpr (requires { real(clx); }) - return real(clx); - } -}; - -} // namespace detail::real_impl - -inline namespace cpo { - -MP_UNITS_EXPORT inline constexpr ::mp_units::detail::real_impl::real_t real; - -} - -namespace detail::imag_impl { - -void imag() = delete; // poison pill - -struct imag_t { - template - [[nodiscard]] constexpr auto operator()(const T& clx) const - { - if constexpr (requires { clx.imag(); }) - return clx.imag(); - else if constexpr (requires { imag(clx); }) - return imag(clx); - } -}; - -} // namespace detail::imag_impl - -inline namespace cpo { - -MP_UNITS_EXPORT inline constexpr ::mp_units::detail::imag_impl::imag_t imag; - -} - -namespace detail::modulus_impl { - -void modulus() = delete; // poison pill - -struct modulus_t { - template - [[nodiscard]] constexpr auto operator()(const T& clx) const - { - if constexpr (requires { clx.modulus(); }) - return clx.modulus(); - else if constexpr (requires { modulus(clx); }) - return modulus(clx); - // `std` made a precedence of using `abs` for modulo on `std::complex` - else if constexpr (requires { abs(clx); }) - return abs(clx); - } -}; - -} // namespace detail::modulus_impl - -inline namespace cpo { - -MP_UNITS_EXPORT inline constexpr ::mp_units::detail::modulus_impl::modulus_t modulus; - -} - -MP_UNITS_EXPORT_BEGIN - /** * @brief A type trait that defines zero, one, min, and max for a representation type * diff --git a/src/core/include/mp-units/framework/representation_concepts.h b/src/core/include/mp-units/framework/representation_concepts.h index 66a6db2ff..62f2c25cb 100644 --- a/src/core/include/mp-units/framework/representation_concepts.h +++ b/src/core/include/mp-units/framework/representation_concepts.h @@ -102,6 +102,79 @@ concept ScalarRepresentation = Scalar && WeaklyRegular && requires(T a, T { a / b } -> Scalar; }; +namespace real_impl { + +void real() = delete; // poison pill + +struct real_t { + [[nodiscard]] constexpr ScalarRepresentation auto operator()(const WeaklyRegular auto& clx) const + { + if constexpr (requires { clx.real(); }) + return clx.real(); + else if constexpr (requires { real(clx); }) + return real(clx); + } +}; + +} // namespace real_impl + +} // namespace detail + +inline namespace cpo { + +MP_UNITS_EXPORT inline constexpr ::mp_units::detail::real_impl::real_t real; + +} + +namespace detail::imag_impl { + +void imag() = delete; // poison pill + +struct imag_t { + [[nodiscard]] constexpr ScalarRepresentation auto operator()(const WeaklyRegular auto& clx) const + { + if constexpr (requires { clx.imag(); }) + return clx.imag(); + else if constexpr (requires { imag(clx); }) + return imag(clx); + } +}; + +} // namespace detail::imag_impl + +inline namespace cpo { + +MP_UNITS_EXPORT inline constexpr ::mp_units::detail::imag_impl::imag_t imag; + +} + +namespace detail::modulus_impl { + +void modulus() = delete; // poison pill + +struct modulus_t { + [[nodiscard]] constexpr ScalarRepresentation auto operator()(const WeaklyRegular auto& clx) const + { + if constexpr (requires { clx.modulus(); }) + return clx.modulus(); + else if constexpr (requires { modulus(clx); }) + return modulus(clx); + // `std` made a precedence of using `abs` for modulo on `std::complex` + else if constexpr (requires { abs(clx); }) + return abs(clx); + } +}; + +} // namespace detail::modulus_impl + +inline namespace cpo { + +MP_UNITS_EXPORT inline constexpr ::mp_units::detail::modulus_impl::modulus_t modulus; + +} + +namespace detail { + template concept ComplexRepresentation = Complex && WeaklyRegular && requires(T a, T b, scaling_factor_type_t f) { // scaling @@ -118,13 +191,46 @@ concept ComplexRepresentation = Complex && WeaklyRegular && requires(T a, { a - b } -> Complex; { a* b } -> Complex; { a / b } -> Complex; - { ::mp_units::real(a) } -> Scalar; - { ::mp_units::imag(a) } -> Scalar; - { ::mp_units::modulus(a) } -> Scalar; + ::mp_units::real(a); + ::mp_units::imag(a); + ::mp_units::modulus(a); }; // TODO how to check for a complex(Scalar, Scalar) -> Complex? +namespace norm_impl { + +void norm() = delete; // poison pill + +struct norm_t { + [[nodiscard]] constexpr ScalarRepresentation auto operator()(const WeaklyRegular auto& vec) const + { + if constexpr (requires { vec.norm(); }) + return vec.norm(); + else if constexpr (requires { norm(vec); }) + return norm(vec); + else if constexpr (requires { vec.magnitude(); }) + return vec.magnitude(); + else if constexpr (requires { magnitude(vec); }) + return magnitude(vec); + // TODO Is it a good idea to enable fundamental types to represent vector quantities? + // else if constexpr (is_scalar) + // return std::abs(vec); + } +}; + +} // namespace norm_impl + +} // namespace detail + +inline namespace cpo { + +MP_UNITS_EXPORT inline constexpr ::mp_units::detail::norm_impl::norm_t norm; + +} + +namespace detail { + template concept VectorRepresentation = Vector && WeaklyRegular && requires(T a, T b, scaling_factor_type_t f) { // scaling @@ -136,7 +242,7 @@ concept VectorRepresentation = Vector && WeaklyRegular && requires(T a, T { -a } -> Vector; { a + b } -> Vector; { a - b } -> Vector; - { ::mp_units::norm(a) } -> Scalar; + ::mp_units::norm(a); // TBD // { zero_vector() } -> Vector; // { unit_vector(a) } -> Vector;