From 4b1f7cd2171f3c7ba0d4da16aee05d40bf7f46c6 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Wed, 12 Feb 2025 18:57:06 +0100 Subject: [PATCH] feat: :boom: `Representation` concept removed --- .../include/mp-units/framework/quantity.h | 60 +++++++++++-------- .../framework/representation_concepts.h | 24 ++++---- .../include/mp-units/framework/value_cast.h | 14 ++--- src/core/include/mp-units/math.h | 4 +- test/static/concepts_test.cpp | 14 ----- test/static/custom_rep_test_min_impl.cpp | 4 +- 6 files changed, 57 insertions(+), 63 deletions(-) diff --git a/src/core/include/mp-units/framework/quantity.h b/src/core/include/mp-units/framework/quantity.h index 914e72f4..60be8839 100644 --- a/src/core/include/mp-units/framework/quantity.h +++ b/src/core/include/mp-units/framework/quantity.h @@ -64,14 +64,22 @@ template template concept IsFloatingPoint = treat_as_floating_point; -template -concept ValuePreservingTo = Representation> && Representation && - Unit && +template +concept ValuePreservingTo = Unit && Unit && std::assignable_from && (IsFloatingPoint || (!IsFloatingPoint> && integral_conversion_factor(FromUnit, ToUnit) && !overflows_non_zero_values(FromUnit, ToUnit))); +template +concept RepresentationValuePreservingTo = + QuantitySpec && RepresentationOf, QS> && + ValuePreservingTo; + +template +concept ScalarRepresentationValuePreservingTo = + ScalarRepresentation> && ValuePreservingTo; + template concept QuantityConvertibleTo = Quantity && Quantity && implicitly_convertible(QFrom::quantity_spec, QTo::quantity_spec) && @@ -103,7 +111,7 @@ template using common_quantity_for = quantity>; -template +template [[nodiscard]] consteval bool overflows_non_zero_common_values(U1 u1, U2 u2) { constexpr Unit auto cu = get_common_unit(U1{}, U2{}); @@ -196,7 +204,7 @@ public: { } - template FwdValue> + template FwdValue> requires detail::ConvertibleWithNumber constexpr explicit(false) quantity(FwdValue&& val) : numerical_value_is_an_implementation_detail_(std::forward(val)) @@ -222,7 +230,7 @@ public: quantity& operator=(const quantity&) = default; quantity& operator=(quantity&&) = default; - template FwdValue> + template FwdValue> requires detail::ConvertibleWithNumber constexpr quantity& operator=(FwdValue&& val) { @@ -428,7 +436,7 @@ public: return std::forward(lhs); } - template Q, detail::ValuePreservingTo Value> + template Q, detail::ScalarRepresentationValuePreservingTo Value> requires(!Quantity) && requires(rep& a, const Value b) { { a *= b } -> std::same_as; } @@ -441,8 +449,8 @@ public: } template Q1, QuantityOf Q2> - requires detail::ConvertibleWithNumber && detail::ValuePreservingTo && - requires(rep& a, const Q2::rep b) { + requires detail::ConvertibleWithNumber && + detail::ScalarRepresentationValuePreservingTo && requires(rep& a, const Q2::rep b) { { a *= b } -> std::same_as; } friend constexpr decltype(auto) operator*=(Q1&& lhs, const Q2& rhs) @@ -450,7 +458,7 @@ public: return std::forward(lhs) *= rhs.numerical_value_is_an_implementation_detail_; } - template Q, detail::ValuePreservingTo Value> + template Q, detail::ScalarRepresentationValuePreservingTo Value> requires(!Quantity) && requires(rep& a, const Value b) { { a /= b } -> std::same_as; } @@ -464,8 +472,8 @@ public: } template Q1, QuantityOf Q2> - requires detail::ConvertibleWithNumber && detail::ValuePreservingTo && - requires(rep& a, const Q2::rep b) { + requires detail::ConvertibleWithNumber && + detail::ScalarRepresentationValuePreservingTo && requires(rep& a, const Q2::rep b) { { a /= b } -> std::same_as; } friend constexpr decltype(auto) operator/=(Q1&& lhs, const Q2& rhs) @@ -485,7 +493,7 @@ public: ret::reference}; } - template Q, Representation Value> + template Q, RepresentationOf Value> requires detail::ConvertibleWithNumber && detail::InvokeResultOf, Rep, const Value&> [[nodiscard]] friend constexpr Quantity auto operator+(const Q& lhs, const Value& rhs) @@ -493,7 +501,7 @@ public: return lhs + ::mp_units::quantity{rhs}; } - template Q, Representation Value> + template Q, RepresentationOf Value> requires detail::ConvertibleWithNumber && detail::InvokeResultOf, Rep, const Value&> [[nodiscard]] friend constexpr Quantity auto operator+(const Value& lhs, const Q& rhs) @@ -512,7 +520,7 @@ public: ret::reference}; } - template Q, Representation Value> + template Q, RepresentationOf Value> requires detail::ConvertibleWithNumber && detail::InvokeResultOf, Rep, const Value&> [[nodiscard]] friend constexpr Quantity auto operator-(const Q& lhs, const Value& rhs) @@ -520,7 +528,7 @@ public: return lhs - ::mp_units::quantity{rhs}; } - template Q, Representation Value> + template Q, RepresentationOf Value> requires detail::ConvertibleWithNumber && detail::InvokeResultOf, Rep, const Value&> [[nodiscard]] friend constexpr Quantity auto operator-(const Value& lhs, const Q& rhs) @@ -541,7 +549,7 @@ public: ret::reference}; } - template Q, Representation Value> + template Q, RepresentationOf Value> requires detail::ConvertibleWithNumber && detail::InvokeResultOf, Rep, const Value&> [[nodiscard]] friend constexpr Quantity auto operator%(const Q& lhs, const Value& rhs) @@ -549,7 +557,7 @@ public: return lhs % ::mp_units::quantity{rhs}; } - template Q, Representation Value> + template Q, RepresentationOf Value> requires detail::ConvertibleWithNumber && detail::InvokeResultOf, Rep, const Value&> [[nodiscard]] friend constexpr Quantity auto operator%(const Value& lhs, const Q& rhs) @@ -617,7 +625,7 @@ public: return ct_lhs.numerical_value_ref_in(ct::unit) == ct_rhs.numerical_value_ref_in(ct::unit); } - template Q, Representation Value> + template Q, RepresentationOf Value> requires detail::ConvertibleWithNumber && std::equality_comparable_with [[nodiscard]] friend constexpr bool operator==(const Q& lhs, const Value& rhs) { @@ -635,7 +643,7 @@ public: return ct_lhs.numerical_value_ref_in(ct::unit) <=> ct_rhs.numerical_value_ref_in(ct::unit); } - template Q, Representation Value> + template Q, RepresentationOf Value> requires detail::ConvertibleWithNumber && std::three_way_comparable_with [[nodiscard]] friend constexpr auto operator<=>(const Q& lhs, const Value& rhs) { @@ -644,10 +652,14 @@ public: }; // CTAD -template +template Value> quantity(Value v, R) -> quantity; -template +#if MP_UNITS_COMP_GCC == 14 +template +#else +template Value> +#endif explicit(false) quantity(Value) -> quantity; template @@ -672,14 +684,14 @@ struct std::common_type { std::common_type_t>; }; -template +template Value> requires(Q::unit == mp_units::one) && requires { typename mp_units::quantity>; } struct std::common_type { using type = mp_units::quantity>; }; -template +template Value> requires requires { typename std::common_type; } struct std::common_type : std::common_type {}; diff --git a/src/core/include/mp-units/framework/representation_concepts.h b/src/core/include/mp-units/framework/representation_concepts.h index b9fad735..69668c74 100644 --- a/src/core/include/mp-units/framework/representation_concepts.h +++ b/src/core/include/mp-units/framework/representation_concepts.h @@ -328,27 +328,23 @@ concept VectorRepresentation = NotQuantity && Vector && ScalableByFactor // concept TensorRepresentation = NotQuantity && Tensor; -} // namespace detail - -MP_UNITS_EXPORT template -concept Representation = - detail::ScalarRepresentation || detail::VectorRepresentation; // || detail::TensorRepresentation; - -namespace detail { - template -concept IsOfCharacter = - (Ch == quantity_character::real_scalar && RealScalar) || - (Ch == quantity_character::complex_scalar && ComplexScalar) || - (Ch == quantity_character::vector && Vector); // || (Ch == quantity_character::tensor && Tensor); +concept IsOfCharacter = (Ch == quantity_character::real_scalar && RealScalarRepresentation) || + (Ch == quantity_character::complex_scalar && ComplexScalarRepresentation) || + (Ch == quantity_character::vector && VectorRepresentation); +// || (Ch == quantity_character::tensor && TensorRepresentation); + +template +concept SomeRepresentation = + detail::ScalarRepresentation || detail::VectorRepresentation; // || detail::TensorRepresentation; } // namespace detail MP_UNITS_EXPORT template concept RepresentationOf = - Representation && ((QuantitySpec && - (detail::QuantityKindSpec || detail::IsOfCharacter)) || + ((detail::QuantityKindSpec && detail::SomeRepresentation) || + detail::IsOfCharacter)) || (std::same_as && detail::IsOfCharacter)); } // namespace mp_units diff --git a/src/core/include/mp-units/framework/value_cast.h b/src/core/include/mp-units/framework/value_cast.h index aaa1ed9c..c3fa8708 100644 --- a/src/core/include/mp-units/framework/value_cast.h +++ b/src/core/include/mp-units/framework/value_cast.h @@ -37,7 +37,7 @@ namespace mp_units { namespace detail { -template +template [[nodiscard]] consteval bool overflows_non_zero_values(UFrom from, UTo to) { if constexpr (is_same_v || treat_as_floating_point) @@ -87,7 +87,7 @@ template> * * @tparam ToRep a representation type to use for a target quantity */ -template> +template> requires RepresentationOf && std::constructible_from [[nodiscard]] constexpr quantity value_cast(FwdQ&& q) { @@ -105,7 +105,7 @@ template> +template> requires detail::UnitCompatibleWith && (!detail::overflows_non_zero_values(Q::unit, ToU)) && RepresentationOf && std::constructible_from @@ -114,7 +114,7 @@ template>(std::forward(q)); } -template> +template> requires detail::UnitCompatibleWith && (!detail::overflows_non_zero_values(Q::unit, ToU)) && RepresentationOf && std::constructible_from @@ -176,7 +176,7 @@ template> +template> requires RepresentationOf && std::constructible_from [[nodiscard]] constexpr quantity_point value_cast(FwdQP&& qp) { @@ -195,7 +195,7 @@ template> +template> requires detail::UnitCompatibleWith && (!detail::overflows_non_zero_values(QP::unit, ToU)) && RepresentationOf && std::constructible_from @@ -206,7 +206,7 @@ template> +template> requires detail::UnitCompatibleWith && (!detail::overflows_non_zero_values(QP::unit, ToU)) && RepresentationOf && std::constructible_from diff --git a/src/core/include/mp-units/math.h b/src/core/include/mp-units/math.h index 5fcf72c1..1e51286a 100644 --- a/src/core/include/mp-units/math.h +++ b/src/core/include/mp-units/math.h @@ -318,8 +318,8 @@ template * @tparam Q Quantity type being the base of the operation * @return Quantity The epsilon value for quantity's representation type */ -template - requires requires { std::numeric_limits::epsilon(); } +template + requires RepresentationOf && requires { std::numeric_limits::epsilon(); } [[deprecated( "2.5.0: Use `std::numeric_limits::epsilon()` instead")]] [[nodiscard]] constexpr quantity epsilon(R r) noexcept diff --git a/test/static/concepts_test.cpp b/test/static/concepts_test.cpp index e7113bbc..c74bb03e 100644 --- a/test/static/concepts_test.cpp +++ b/test/static/concepts_test.cpp @@ -315,20 +315,6 @@ static_assert(ReferenceOf); static_assert(!ReferenceOf); static_assert(!ReferenceOf); -// Representation -static_assert(Representation); -static_assert(Representation); -static_assert(!Representation); -static_assert(!Representation>); -#if MP_UNITS_HOSTED -static_assert(Representation>); -static_assert(Representation>); -static_assert(Representation>); -static_assert(Representation>); -static_assert(!Representation); -static_assert(!Representation); -#endif - // RepresentationOf static_assert(RepresentationOf); static_assert(!RepresentationOf); diff --git a/test/static/custom_rep_test_min_impl.cpp b/test/static/custom_rep_test_min_impl.cpp index a07524d0..738d8e53 100644 --- a/test/static/custom_rep_test_min_impl.cpp +++ b/test/static/custom_rep_test_min_impl.cpp @@ -71,8 +71,8 @@ namespace { using namespace mp_units; -static_assert(Representation>); -static_assert(Representation>); +static_assert(RepresentationOf, quantity_character::real_scalar>); +static_assert(RepresentationOf, quantity_character::real_scalar>); // construction from a value is not allowed static_assert(!std::constructible_from>, min_impl>);