From a223c08a39ff583a87898c926c9a6d712f8b5f99 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Thu, 28 Nov 2024 23:02:11 +0100 Subject: [PATCH] refactor: multiplication and division by scalars was a bad idea for `Complex` and `Vector` --- .../framework/representation_concepts.h | 82 +++++++++---------- test/static/concepts_test.cpp | 10 +++ 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/src/core/include/mp-units/framework/representation_concepts.h b/src/core/include/mp-units/framework/representation_concepts.h index 414c08752..384479a72 100644 --- a/src/core/include/mp-units/framework/representation_concepts.h +++ b/src/core/include/mp-units/framework/representation_concepts.h @@ -168,22 +168,18 @@ constexpr bool disable_complex = false; namespace detail { template -concept Complex = - (!disable_complex) && WeaklyRegular && Scalar> && - std::constructible_from, value_type_t> && requires(T a, T b, value_type_t s) { - // complex operations - { -a } -> std::common_with; - { a + b } -> std::common_with; - { a - b } -> std::common_with; - { a* b } -> std::common_with; - { a / b } -> std::common_with; - { a* s } -> std::common_with; - { s* a } -> std::common_with; - { a / s } -> std::common_with; - ::mp_units::real(a); - ::mp_units::imag(a); - ::mp_units::modulus(a); - }; +concept Complex = (!disable_complex) && WeaklyRegular && requires(T a, T b) { + // complex operations + { -a } -> std::common_with; + { a + b } -> std::common_with; + { a - b } -> std::common_with; + { a* b } -> std::common_with; + { a / b } -> std::common_with; + ::mp_units::real(a); + ::mp_units::imag(a); + ::mp_units::modulus(a); + requires std::constructible_from; +}; namespace magnitude_impl { @@ -233,23 +229,19 @@ constexpr bool disable_vector = false; namespace detail { template -concept Vector = - (!disable_vector) && WeaklyRegular && Scalar> && requires(T a, T b, value_type_t s) { - // vector operations - { -a } -> std::common_with; - { a + b } -> std::common_with; - { a - b } -> std::common_with; - { a* s } -> std::common_with; - { s* a } -> std::common_with; - { a / s } -> std::common_with; - ::mp_units::magnitude(a); - // TODO should we check for the below as well (e.g., when `size() > 1` or `2`) - // { zero_vector() } -> Vector; - // { unit_vector(a) } -> Vector; - // { scalar_product(a, b) } -> Scalar; - // { vector_product(a, b) } -> Vector; - // { tensor_product(a, b) } -> Tensor2; - }; +concept Vector = (!disable_vector) && WeaklyRegular && requires(T a, T b) { + // vector operations + { -a } -> std::common_with; + { a + b } -> std::common_with; + { a - b } -> std::common_with; + ::mp_units::magnitude(a); + // TODO should we also check for the below (e.g., when `size() > 1` or `2`) + // { zero_vector() } -> Vector; + // { unit_vector(a) } -> Vector; + // { scalar_product(a, b) } -> Scalar; + // { vector_product(a, b) } -> Vector; + // { tensor_product(a, b) } -> Tensor2; +}; // TODO provide when some actual operations will be required // template @@ -266,27 +258,33 @@ constexpr bool is_quantity = false; template using scaling_factor_type_t = conditional, long double, std::intmax_t>; +// TODO how can we use `(!Quantity)` below? template -concept ScalarRepresentation = (!is_quantity) && Scalar && requires(T a, T b, scaling_factor_type_t f) { +concept ScalarRepresentation = (!is_quantity) && Scalar && requires(T v, scaling_factor_type_t f) { // scaling - { a* f } -> std::common_with; - { f* a } -> std::common_with; - { a / f } -> std::common_with; + { v* f } -> std::common_with; + { f* v } -> std::common_with; + { v / f } -> std::common_with; }; template -concept ComplexRepresentation = (!is_quantity) && Complex && requires(T a, T b, scaling_factor_type_t f) { +concept ComplexRepresentation = (!is_quantity) && Complex && requires(T v, scaling_factor_type_t f) { // scaling // TODO The below conversion to `T` is an exception compared to other representation types // `std::complex` * `U` do not work, but `std::complex` is convertible from `U` // Maybe expose this as a customization point? - { a* T(f) } -> std::common_with; - { T(f) * a } -> std::common_with; - { a / T(f) } -> std::common_with; + { v* T(f) } -> std::common_with; + { T(f) * v } -> std::common_with; + { v / T(f) } -> std::common_with; }; template -concept VectorRepresentation = (!is_quantity) && Vector; +concept VectorRepresentation = (!is_quantity) && Vector && requires(T v, scaling_factor_type_t f) { + // scaling + { v* f } -> std::common_with; + { f* v } -> std::common_with; + { v / f } -> std::common_with; +}; // template // concept TensorRepresentation = (!is_quantity) && Tensor; diff --git a/test/static/concepts_test.cpp b/test/static/concepts_test.cpp index d0d4552b0..2ee71fbd6 100644 --- a/test/static/concepts_test.cpp +++ b/test/static/concepts_test.cpp @@ -434,4 +434,14 @@ static_assert(!QuantityPointLike>); static_assert(!QuantityPointLike>); static_assert(!QuantityPointLike); +// Quantity Characters + +static_assert(detail::Scalar>); +static_assert(detail::Scalar>); +static_assert(!detail::Scalar>); +static_assert(!detail::Scalar>); +// TODO it would be make the below work +static_assert(!detail::Scalar>); +static_assert(!detail::Scalar>); + } // namespace