feat: explicit constructor now can perform an explicit quantity_spec conversion

This commit is contained in:
Mateusz Pusz
2025-06-20 17:10:34 +02:00
parent 723e3dfa68
commit 9c140f4b3a
4 changed files with 18 additions and 13 deletions

View File

@ -95,7 +95,7 @@ concept ValuePreservingScaling2Reps =
template<typename QTo, typename QFrom> template<typename QTo, typename QFrom>
concept QuantityConstructibleFrom = concept QuantityConstructibleFrom =
Quantity<QTo> && Quantity<QFrom> && implicitly_convertible(QFrom::quantity_spec, QTo::quantity_spec) && Quantity<QTo> && Quantity<QFrom> && explicitly_convertible(QFrom::quantity_spec, QTo::quantity_spec) &&
ValuePreservingConstruction<typename QTo::rep, typename QFrom::rep> && ValuePreservingConstruction<typename QTo::rep, typename QFrom::rep> &&
ValuePreservingScaling2Reps<QFrom::unit, typename QFrom::rep, QTo::unit, typename QTo::rep>; ValuePreservingScaling2Reps<QFrom::unit, typename QFrom::rep, QTo::unit, typename QTo::rep>;
@ -218,7 +218,8 @@ public:
template<auto R2, typename Rep2> template<auto R2, typename Rep2>
requires detail::QuantityConstructibleFrom<quantity, quantity<R2, Rep2>> requires detail::QuantityConstructibleFrom<quantity, quantity<R2, Rep2>>
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
constexpr explicit(!std::convertible_to<Rep2, rep>) quantity(const quantity<R2, Rep2>& q) : constexpr explicit(!implicitly_convertible(get_quantity_spec(R2), quantity_spec) || !std::convertible_to<Rep2, rep>)
quantity(const quantity<R2, Rep2>& q) :
quantity(detail::sudo_cast<quantity>(q)) quantity(detail::sudo_cast<quantity>(q))
{ {
} }
@ -227,7 +228,7 @@ public:
requires detail::QuantityConstructibleFrom<quantity, detail::quantity_like_type<Q>> requires detail::QuantityConstructibleFrom<quantity, detail::quantity_like_type<Q>>
constexpr explicit(quantity_like_traits<Q>::explicit_import || constexpr explicit(quantity_like_traits<Q>::explicit_import ||
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
!std::convertible_to<typename quantity_like_traits<Q>::rep, Rep>) quantity(const Q& q) : !std::convertible_to<detail::quantity_like_type<Q>, quantity>) quantity(const Q& q) :
quantity(::mp_units::quantity{quantity_like_traits<Q>::to_numerical_value(q), quantity_like_traits<Q>::reference}) quantity(::mp_units::quantity{quantity_like_traits<Q>::to_numerical_value(q), quantity_like_traits<Q>::reference})
{ {
} }
@ -335,7 +336,7 @@ public:
template<typename Q_, QuantityLike Q = std::remove_cvref_t<Q_>> template<typename Q_, QuantityLike Q = std::remove_cvref_t<Q_>>
requires detail::QuantityConstructibleFrom<detail::quantity_like_type<Q>, quantity> requires detail::QuantityConstructibleFrom<detail::quantity_like_type<Q>, quantity>
[[nodiscard]] explicit(quantity_like_traits<Q>::explicit_export || [[nodiscard]] explicit(quantity_like_traits<Q>::explicit_export ||
!std::convertible_to<rep, typename quantity_like_traits<Q>::rep>) constexpr !std::convertible_to<quantity, detail::quantity_like_type<Q>>) constexpr
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
operator Q_() const operator Q_() const
noexcept(noexcept(quantity_like_traits<Q>::from_numerical_value(numerical_value_is_an_implementation_detail_)) && noexcept(noexcept(quantity_like_traits<Q>::from_numerical_value(numerical_value_is_an_implementation_detail_)) &&

View File

@ -215,8 +215,7 @@ public:
~quantity_point() = default; ~quantity_point() = default;
template<typename FwdQ, QuantityOf<quantity_spec> Q = std::remove_cvref_t<FwdQ>> template<typename FwdQ, QuantityOf<quantity_spec> Q = std::remove_cvref_t<FwdQ>>
requires std::constructible_from<quantity_type, FwdQ> && (point_origin == default_point_origin(R)) && requires std::constructible_from<quantity_type, FwdQ> && (point_origin == default_point_origin(R))
(implicitly_convertible(Q::quantity_spec, quantity_spec))
constexpr explicit quantity_point(FwdQ&& q) : quantity_from_origin_is_an_implementation_detail_(std::forward<FwdQ>(q)) constexpr explicit quantity_point(FwdQ&& q) : quantity_from_origin_is_an_implementation_detail_(std::forward<FwdQ>(q))
{ {
} }
@ -252,9 +251,8 @@ public:
template<QuantityPointLike QP> template<QuantityPointLike QP>
requires(quantity_point_like_traits<QP>::point_origin == point_origin) && requires(quantity_point_like_traits<QP>::point_origin == point_origin) &&
std::convertible_to< std::constructible_from<quantity_type, quantity<quantity_point_like_traits<QP>::reference,
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>, typename quantity_point_like_traits<QP>::rep>>
quantity_type>
constexpr explicit( constexpr explicit(
quantity_point_like_traits<QP>::explicit_import || quantity_point_like_traits<QP>::explicit_import ||
!std::convertible_to< !std::convertible_to<

View File

@ -705,8 +705,8 @@ static_assert(
!std::convertible_to<quantity_point<si::kelvin, si::ice_point>, quantity_point<isq::height[m], mean_sea_level>>); !std::convertible_to<quantity_point<si::kelvin, si::ice_point>, quantity_point<isq::height[m], mean_sea_level>>);
// non-convertible quantity_specs // non-convertible quantity_specs
static_assert(!std::constructible_from<quantity_point<special_height[m], mean_sea_level>, static_assert(std::constructible_from<quantity_point<special_height[m], mean_sea_level>,
quantity_point<isq::height[m], mean_sea_level>>); quantity_point<isq::height[m], mean_sea_level>>);
static_assert(!std::convertible_to<quantity_point<isq::height[m], mean_sea_level>, static_assert(!std::convertible_to<quantity_point<isq::height[m], mean_sea_level>,
quantity_point<special_height[m], mean_sea_level>>); quantity_point<special_height[m], mean_sea_level>>);
@ -766,8 +766,8 @@ static_assert(std::constructible_from<quantity_point<isq::height[m], mean_sea_le
static_assert(std::convertible_to<quantity_point<special_height[m], mean_sea_level>, static_assert(std::convertible_to<quantity_point<special_height[m], mean_sea_level>,
quantity_point<isq::height[m], mean_sea_level>>); quantity_point<isq::height[m], mean_sea_level>>);
static_assert(!std::constructible_from<quantity_point<special_height[m], mean_sea_level>, static_assert(std::constructible_from<quantity_point<special_height[m], mean_sea_level>,
quantity_point<isq::height[m], mean_sea_level>>); quantity_point<isq::height[m], mean_sea_level>>);
static_assert(!std::convertible_to<quantity_point<isq::height[m], mean_sea_level>, static_assert(!std::convertible_to<quantity_point<isq::height[m], mean_sea_level>,
quantity_point<special_height[m], mean_sea_level>>); quantity_point<special_height[m], mean_sea_level>>);

View File

@ -224,6 +224,7 @@ static_assert(std::convertible_to<quantity<si::metre, cartesian_vector<double>>,
quantity<isq::position_vector[m], cartesian_vector<double>>>); quantity<isq::position_vector[m], cartesian_vector<double>>>);
#endif #endif
// conversion between different quantities not allowed // conversion between different quantities not allowed
static_assert(!std::constructible_from<quantity<isq::length[m]>, quantity<isq::time[s]>>); static_assert(!std::constructible_from<quantity<isq::length[m]>, quantity<isq::time[s]>>);
static_assert(!std::convertible_to<quantity<isq::time[s]>, quantity<isq::length[m]>>); static_assert(!std::convertible_to<quantity<isq::time[s]>, quantity<isq::length[m]>>);
@ -263,6 +264,11 @@ static_assert(!std::convertible_to<quantity<rad>, quantity<one>>);
static_assert(!std::convertible_to<quantity<isq::angular_measure[one]>, quantity<dimensionless[one]>>); static_assert(!std::convertible_to<quantity<isq::angular_measure[one]>, quantity<dimensionless[one]>>);
static_assert(!std::convertible_to<quantity<isq::angular_measure[one]>, quantity<one>>); static_assert(!std::convertible_to<quantity<isq::angular_measure[one]>, quantity<one>>);
// explicit-construction only
static_assert(std::constructible_from<quantity<isq::distance[m]>, quantity<isq::length[m]>>);
static_assert(!std::convertible_to<quantity<isq::length[m]>, quantity<isq::distance[m]>>);
/////////////////////// ///////////////////////
// obtaining a number // obtaining a number
/////////////////////// ///////////////////////