From 9c140f4b3ad7e35f8486cf6f7bcf822e33ab7274 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Fri, 20 Jun 2025 17:10:34 +0200 Subject: [PATCH] feat: explicit constructor now can perform an explicit `quantity_spec` conversion --- src/core/include/mp-units/framework/quantity.h | 9 +++++---- src/core/include/mp-units/framework/quantity_point.h | 8 +++----- test/static/quantity_point_test.cpp | 8 ++++---- test/static/quantity_test.cpp | 6 ++++++ 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/core/include/mp-units/framework/quantity.h b/src/core/include/mp-units/framework/quantity.h index c44be919..e9bc2813 100644 --- a/src/core/include/mp-units/framework/quantity.h +++ b/src/core/include/mp-units/framework/quantity.h @@ -95,7 +95,7 @@ concept ValuePreservingScaling2Reps = template concept QuantityConstructibleFrom = - Quantity && Quantity && implicitly_convertible(QFrom::quantity_spec, QTo::quantity_spec) && + Quantity && Quantity && explicitly_convertible(QFrom::quantity_spec, QTo::quantity_spec) && ValuePreservingConstruction && ValuePreservingScaling2Reps; @@ -218,7 +218,8 @@ public: template requires detail::QuantityConstructibleFrom> // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) - constexpr explicit(!std::convertible_to) quantity(const quantity& q) : + constexpr explicit(!implicitly_convertible(get_quantity_spec(R2), quantity_spec) || !std::convertible_to) + quantity(const quantity& q) : quantity(detail::sudo_cast(q)) { } @@ -227,7 +228,7 @@ public: requires detail::QuantityConstructibleFrom> constexpr explicit(quantity_like_traits::explicit_import || // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) - !std::convertible_to::rep, Rep>) quantity(const Q& q) : + !std::convertible_to, quantity>) quantity(const Q& q) : quantity(::mp_units::quantity{quantity_like_traits::to_numerical_value(q), quantity_like_traits::reference}) { } @@ -335,7 +336,7 @@ public: template> requires detail::QuantityConstructibleFrom, quantity> [[nodiscard]] explicit(quantity_like_traits::explicit_export || - !std::convertible_to::rep>) constexpr + !std::convertible_to>) constexpr // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) operator Q_() const noexcept(noexcept(quantity_like_traits::from_numerical_value(numerical_value_is_an_implementation_detail_)) && diff --git a/src/core/include/mp-units/framework/quantity_point.h b/src/core/include/mp-units/framework/quantity_point.h index dd535a7b..a67c57e4 100644 --- a/src/core/include/mp-units/framework/quantity_point.h +++ b/src/core/include/mp-units/framework/quantity_point.h @@ -215,8 +215,7 @@ public: ~quantity_point() = default; template Q = std::remove_cvref_t> - requires std::constructible_from && (point_origin == default_point_origin(R)) && - (implicitly_convertible(Q::quantity_spec, quantity_spec)) + requires std::constructible_from && (point_origin == default_point_origin(R)) constexpr explicit quantity_point(FwdQ&& q) : quantity_from_origin_is_an_implementation_detail_(std::forward(q)) { } @@ -252,9 +251,8 @@ public: template requires(quantity_point_like_traits::point_origin == point_origin) && - std::convertible_to< - quantity::reference, typename quantity_point_like_traits::rep>, - quantity_type> + std::constructible_from::reference, + typename quantity_point_like_traits::rep>> constexpr explicit( quantity_point_like_traits::explicit_import || !std::convertible_to< diff --git a/test/static/quantity_point_test.cpp b/test/static/quantity_point_test.cpp index 67fc8e80..866ce99c 100644 --- a/test/static/quantity_point_test.cpp +++ b/test/static/quantity_point_test.cpp @@ -705,8 +705,8 @@ static_assert( !std::convertible_to, quantity_point>); // non-convertible quantity_specs -static_assert(!std::constructible_from, - quantity_point>); +static_assert(std::constructible_from, + quantity_point>); static_assert(!std::convertible_to, quantity_point>); @@ -766,8 +766,8 @@ static_assert(std::constructible_from, quantity_point>); -static_assert(!std::constructible_from, - quantity_point>); +static_assert(std::constructible_from, + quantity_point>); static_assert(!std::convertible_to, quantity_point>); diff --git a/test/static/quantity_test.cpp b/test/static/quantity_test.cpp index 8b31a0c4..56485bf3 100644 --- a/test/static/quantity_test.cpp +++ b/test/static/quantity_test.cpp @@ -224,6 +224,7 @@ static_assert(std::convertible_to>, quantity>>); #endif + // conversion between different quantities not allowed static_assert(!std::constructible_from, quantity>); static_assert(!std::convertible_to, quantity>); @@ -263,6 +264,11 @@ static_assert(!std::convertible_to, quantity>); static_assert(!std::convertible_to, quantity>); static_assert(!std::convertible_to, quantity>); +// explicit-construction only +static_assert(std::constructible_from, quantity>); +static_assert(!std::convertible_to, quantity>); + + /////////////////////// // obtaining a number ///////////////////////