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>
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> &&
ValuePreservingScaling2Reps<QFrom::unit, typename QFrom::rep, QTo::unit, typename QTo::rep>;
@ -218,7 +218,8 @@ public:
template<auto R2, typename Rep2>
requires detail::QuantityConstructibleFrom<quantity, quantity<R2, Rep2>>
// 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))
{
}
@ -227,7 +228,7 @@ public:
requires detail::QuantityConstructibleFrom<quantity, detail::quantity_like_type<Q>>
constexpr explicit(quantity_like_traits<Q>::explicit_import ||
// 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})
{
}
@ -335,7 +336,7 @@ public:
template<typename Q_, QuantityLike Q = std::remove_cvref_t<Q_>>
requires detail::QuantityConstructibleFrom<detail::quantity_like_type<Q>, quantity>
[[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)
operator Q_() const
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;
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)) &&
(implicitly_convertible(Q::quantity_spec, quantity_spec))
requires std::constructible_from<quantity_type, FwdQ> && (point_origin == default_point_origin(R))
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>
requires(quantity_point_like_traits<QP>::point_origin == point_origin) &&
std::convertible_to<
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>,
quantity_type>
std::constructible_from<quantity_type, quantity<quantity_point_like_traits<QP>::reference,
typename quantity_point_like_traits<QP>::rep>>
constexpr explicit(
quantity_point_like_traits<QP>::explicit_import ||
!std::convertible_to<

View File

@ -705,7 +705,7 @@ static_assert(
!std::convertible_to<quantity_point<si::kelvin, si::ice_point>, quantity_point<isq::height[m], mean_sea_level>>);
// 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>>);
static_assert(!std::convertible_to<quantity_point<isq::height[m], mean_sea_level>,
quantity_point<special_height[m], mean_sea_level>>);
@ -766,7 +766,7 @@ 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>,
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>>);
static_assert(!std::convertible_to<quantity_point<isq::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>>>);
#endif
// conversion between different quantities not allowed
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]>>);
@ -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<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
///////////////////////