fix: disabled partial convertibility of binary operators arguments

This commit is contained in:
Mateusz Pusz
2024-07-12 15:02:29 +02:00
parent e5e0e47c36
commit bc234b0093
2 changed files with 38 additions and 38 deletions

View File

@@ -463,9 +463,9 @@ public:
} }
// binary operators on quantities // binary operators on quantities
template<auto R2, typename Rep2> template<std::derived_from<quantity> Q, auto R2, typename Rep2>
requires detail::CommonlyInvocableQuantities<std::plus<>, quantity, quantity<R2, Rep2>> requires detail::CommonlyInvocableQuantities<std::plus<>, quantity, quantity<R2, Rep2>>
[[nodiscard]] friend constexpr Quantity auto operator+(const quantity& lhs, const quantity<R2, Rep2>& rhs) [[nodiscard]] friend constexpr Quantity auto operator+(const Q& lhs, const quantity<R2, Rep2>& rhs)
{ {
using ret = detail::common_quantity_for<std::plus<>, quantity, quantity<R2, Rep2>>; using ret = detail::common_quantity_for<std::plus<>, quantity, quantity<R2, Rep2>>;
const ret ret_lhs(lhs); const ret ret_lhs(lhs);
@@ -474,9 +474,9 @@ public:
ret::reference}; ret::reference};
} }
template<auto R2, typename Rep2> template<std::derived_from<quantity> Q, auto R2, typename Rep2>
requires detail::CommonlyInvocableQuantities<std::minus<>, quantity, quantity<R2, Rep2>> requires detail::CommonlyInvocableQuantities<std::minus<>, quantity, quantity<R2, Rep2>>
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity& lhs, const quantity<R2, Rep2>& rhs) [[nodiscard]] friend constexpr Quantity auto operator-(const Q& lhs, const quantity<R2, Rep2>& rhs)
{ {
using ret = detail::common_quantity_for<std::minus<>, quantity, quantity<R2, Rep2>>; using ret = detail::common_quantity_for<std::minus<>, quantity, quantity<R2, Rep2>>;
const ret ret_lhs(lhs); const ret ret_lhs(lhs);
@@ -485,10 +485,10 @@ public:
ret::reference}; ret::reference};
} }
template<auto R2, typename Rep2> template<std::derived_from<quantity> Q, auto R2, typename Rep2>
requires(!treat_as_floating_point<Rep>) && (!treat_as_floating_point<Rep2>) && requires(!treat_as_floating_point<Rep>) && (!treat_as_floating_point<Rep2>) &&
detail::CommonlyInvocableQuantities<std::modulus<>, quantity, quantity<R2, Rep2>> detail::CommonlyInvocableQuantities<std::modulus<>, quantity, quantity<R2, Rep2>>
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& lhs, const quantity<R2, Rep2>& rhs) [[nodiscard]] friend constexpr Quantity auto operator%(const Q& lhs, const quantity<R2, Rep2>& rhs)
{ {
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero()); MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
using ret = detail::common_quantity_for<std::modulus<>, quantity, quantity<R2, Rep2>>; using ret = detail::common_quantity_for<std::modulus<>, quantity, quantity<R2, Rep2>>;
@@ -498,58 +498,58 @@ public:
ret::reference}; ret::reference};
} }
template<auto R2, typename Rep2> template<std::derived_from<quantity> Q, auto R2, typename Rep2>
requires detail::InvocableQuantities<std::multiplies<>, quantity, quantity<R2, Rep2>> requires detail::InvocableQuantities<std::multiplies<>, quantity, quantity<R2, Rep2>>
[[nodiscard]] friend constexpr Quantity auto operator*(const quantity& lhs, const quantity<R2, Rep2>& rhs) [[nodiscard]] friend constexpr Quantity auto operator*(const Q& lhs, const quantity<R2, Rep2>& rhs)
{ {
return ::mp_units::quantity{lhs.numerical_value_ref_in(unit) * rhs.numerical_value_ref_in(rhs.unit), R * R2}; return ::mp_units::quantity{lhs.numerical_value_ref_in(unit) * rhs.numerical_value_ref_in(rhs.unit), R * R2};
} }
template<typename Value> template<std::derived_from<quantity> Q, typename Value>
requires(!Quantity<Value>) && requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::multiplies<>, Rep, const Value&> (!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::multiplies<>, Rep, const Value&>
[[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator*(const quantity& q, const Value& v) [[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator*(const Q& q, const Value& v)
{ {
return ::mp_units::quantity{q.numerical_value_ref_in(unit) * v, R}; return ::mp_units::quantity{q.numerical_value_ref_in(unit) * v, R};
} }
template<typename Value> template<typename Value, std::derived_from<quantity> Q>
requires(!Quantity<Value>) && requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::multiplies<>, const Value&, Rep> (!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::multiplies<>, const Value&, Rep>
[[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator*(const Value& v, const quantity& q) [[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator*(const Value& v, const Q& q)
{ {
return ::mp_units::quantity{v * q.numerical_value_ref_in(unit), R}; return ::mp_units::quantity{v * q.numerical_value_ref_in(unit), R};
} }
template<auto R2, typename Rep2> template<std::derived_from<quantity> Q, auto R2, typename Rep2>
requires detail::InvocableQuantities<std::divides<>, quantity, quantity<R2, Rep2>> requires detail::InvocableQuantities<std::divides<>, quantity, quantity<R2, Rep2>>
[[nodiscard]] friend constexpr Quantity auto operator/(const quantity& lhs, const quantity<R2, Rep2>& rhs) [[nodiscard]] friend constexpr Quantity auto operator/(const Q& lhs, const quantity<R2, Rep2>& rhs)
{ {
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero()); MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
return ::mp_units::quantity{lhs.numerical_value_ref_in(unit) / rhs.numerical_value_ref_in(rhs.unit), R / R2}; return ::mp_units::quantity{lhs.numerical_value_ref_in(unit) / rhs.numerical_value_ref_in(rhs.unit), R / R2};
} }
template<typename Value> template<std::derived_from<quantity> Q, typename Value>
requires(!Quantity<Value>) && requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::divides<>, Rep, const Value&> (!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::divides<>, Rep, const Value&>
[[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator/(const quantity& q, const Value& v) [[nodiscard]] friend constexpr QuantityOf<quantity_spec> auto operator/(const Q& q, const Value& v)
{ {
MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero()); MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero());
return ::mp_units::quantity{q.numerical_value_ref_in(unit) / v, R}; return ::mp_units::quantity{q.numerical_value_ref_in(unit) / v, R};
} }
template<typename Value> template<typename Value, std::derived_from<quantity> Q>
requires(!Quantity<Value>) && requires(!Quantity<Value>) &&
(!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::divides<>, const Value&, Rep> (!Reference<Value>) && detail::InvokeResultOf<quantity_spec.character, std::divides<>, const Value&, Rep>
[[nodiscard]] friend constexpr QuantityOf<inverse(quantity_spec)> auto operator/(const Value& v, const quantity& q) [[nodiscard]] friend constexpr QuantityOf<inverse(quantity_spec)> auto operator/(const Value& v, const Q& q)
{ {
return ::mp_units::quantity{v / q.numerical_value_ref_in(unit), ::mp_units::one / R}; return ::mp_units::quantity{v / q.numerical_value_ref_in(unit), ::mp_units::one / R};
} }
template<auto R2, typename Rep2> template<std::derived_from<quantity> Q, auto R2, typename Rep2>
requires requires { typename std::common_type_t<quantity, quantity<R2, Rep2>>; } && requires requires { typename std::common_type_t<quantity, quantity<R2, Rep2>>; } &&
std::equality_comparable<typename std::common_type_t<quantity, quantity<R2, Rep2>>::rep> std::equality_comparable<typename std::common_type_t<quantity, quantity<R2, Rep2>>::rep>
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity<R2, Rep2>& rhs) [[nodiscard]] friend constexpr bool operator==(const Q& lhs, const quantity<R2, Rep2>& rhs)
{ {
using ct = std::common_type_t<quantity, quantity<R2, Rep2>>; using ct = std::common_type_t<quantity, quantity<R2, Rep2>>;
const ct ct_lhs(lhs); const ct ct_lhs(lhs);
@@ -557,10 +557,10 @@ public:
return ct_lhs.numerical_value_ref_in(ct::unit) == ct_rhs.numerical_value_ref_in(ct::unit); return ct_lhs.numerical_value_ref_in(ct::unit) == ct_rhs.numerical_value_ref_in(ct::unit);
} }
template<auto R2, typename Rep2> template<std::derived_from<quantity> Q, auto R2, typename Rep2>
requires requires { typename std::common_type_t<quantity, quantity<R2, Rep2>>; } && requires requires { typename std::common_type_t<quantity, quantity<R2, Rep2>>; } &&
std::three_way_comparable<typename std::common_type_t<quantity, quantity<R2, Rep2>>::rep> std::three_way_comparable<typename std::common_type_t<quantity, quantity<R2, Rep2>>::rep>
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity<R2, Rep2>& rhs) [[nodiscard]] friend constexpr auto operator<=>(const Q& lhs, const quantity<R2, Rep2>& rhs)
{ {
using ct = std::common_type_t<quantity, quantity<R2, Rep2>>; using ct = std::common_type_t<quantity, quantity<R2, Rep2>>;
const ct ct_lhs(lhs); const ct ct_lhs(lhs);

View File

@@ -415,10 +415,10 @@ public:
} }
// binary operators on quantity points // binary operators on quantity points
template<auto R2, typename Rep2> template<std::derived_from<quantity_point> QP, auto R2, typename Rep2>
// TODO simplify when gcc catches up // TODO simplify when gcc catches up
requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R2)), PO.quantity_spec> requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R2)), PO.quantity_spec>
[[nodiscard]] friend constexpr QuantityPoint auto operator+(const quantity_point& qp, const quantity<R2, Rep2>& q) [[nodiscard]] friend constexpr QuantityPoint auto operator+(const QP& qp, const quantity<R2, Rep2>& q)
requires requires { qp.quantity_ref_from(PO) + q; } requires requires { qp.quantity_ref_from(PO) + q; }
{ {
if constexpr (detail::is_zeroth_point_origin(PO)) if constexpr (detail::is_zeroth_point_origin(PO))
@@ -427,19 +427,19 @@ public:
return ::mp_units::quantity_point{qp.quantity_ref_from(PO) + q, PO}; return ::mp_units::quantity_point{qp.quantity_ref_from(PO) + q, PO};
} }
template<auto R1, typename Rep1> template<auto R1, typename Rep1, std::derived_from<quantity_point> QP>
// TODO simplify when gcc catches up // TODO simplify when gcc catches up
requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R1)), PO.quantity_spec> requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R1)), PO.quantity_spec>
[[nodiscard]] friend constexpr QuantityPoint auto operator+(const quantity<R1, Rep1>& q, const quantity_point& qp) [[nodiscard]] friend constexpr QuantityPoint auto operator+(const quantity<R1, Rep1>& q, const QP& qp)
requires requires { q + qp.quantity_ref_from(PO); } requires requires { q + qp.quantity_ref_from(PO); }
{ {
return qp + q; return qp + q;
} }
template<auto R2, typename Rep2> template<std::derived_from<quantity_point> QP, auto R2, typename Rep2>
// TODO simplify when gcc catches up // TODO simplify when gcc catches up
requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R2)), PO.quantity_spec> requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R2)), PO.quantity_spec>
[[nodiscard]] friend constexpr QuantityPoint auto operator-(const quantity_point& qp, const quantity<R2, Rep2>& q) [[nodiscard]] friend constexpr QuantityPoint auto operator-(const QP& qp, const quantity<R2, Rep2>& q)
requires requires { qp.quantity_ref_from(PO) - q; } requires requires { qp.quantity_ref_from(PO) - q; }
{ {
if constexpr (detail::is_zeroth_point_origin(PO)) if constexpr (detail::is_zeroth_point_origin(PO))
@@ -448,8 +448,8 @@ public:
return ::mp_units::quantity_point{qp.quantity_ref_from(PO) - q, PO}; return ::mp_units::quantity_point{qp.quantity_ref_from(PO) - q, PO};
} }
template<QuantityPointOf<absolute_point_origin> QP2> template<std::derived_from<quantity_point> QP, QuantityPointOf<absolute_point_origin> QP2>
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity_point& lhs, const QP2& rhs) [[nodiscard]] friend constexpr Quantity auto operator-(const QP& lhs, const QP2& rhs)
// TODO consider constraining it for both branches // TODO consider constraining it for both branches
requires requires { lhs.quantity_ref_from(point_origin) - rhs.quantity_ref_from(QP2::point_origin); } requires requires { lhs.quantity_ref_from(point_origin) - rhs.quantity_ref_from(QP2::point_origin); }
{ {
@@ -460,10 +460,10 @@ public:
(lhs.point_origin - rhs.point_origin); (lhs.point_origin - rhs.point_origin);
} }
template<PointOrigin PO2> template<std::derived_from<quantity_point> QP, PointOrigin PO2>
requires QuantityPointOf<quantity_point, PO2{}> && requires QuantityPointOf<quantity_point, PO2{}> &&
ReferenceOf<std::remove_const_t<decltype(reference)>, PO2::quantity_spec> ReferenceOf<std::remove_const_t<decltype(reference)>, PO2::quantity_spec>
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity_point& qp, PO2 po) [[nodiscard]] friend constexpr Quantity auto operator-(const QP& qp, PO2 po)
{ {
if constexpr (point_origin == po) if constexpr (point_origin == po)
return qp.quantity_ref_from(point_origin); return qp.quantity_ref_from(point_origin);
@@ -482,17 +482,17 @@ public:
} }
} }
template<PointOrigin PO1> template<PointOrigin PO1, std::derived_from<quantity_point> QP>
requires QuantityPointOf<quantity_point, PO1{}> && requires QuantityPointOf<quantity_point, PO1{}> &&
ReferenceOf<std::remove_const_t<decltype(reference)>, PO1::quantity_spec> ReferenceOf<std::remove_const_t<decltype(reference)>, PO1::quantity_spec>
[[nodiscard]] friend constexpr Quantity auto operator-(PO1 po, const quantity_point& qp) [[nodiscard]] friend constexpr Quantity auto operator-(PO1 po, const QP& qp)
{ {
return -(qp - po); return -(qp - po);
} }
template<QuantityPointOf<absolute_point_origin> QP2> template<std::derived_from<quantity_point> QP, QuantityPointOf<absolute_point_origin> QP2>
requires std::equality_comparable_with<quantity_type, typename QP2::quantity_type> requires std::equality_comparable_with<quantity_type, typename QP2::quantity_type>
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP2& rhs) [[nodiscard]] friend constexpr bool operator==(const QP& lhs, const QP2& rhs)
{ {
if constexpr (point_origin == QP2::point_origin) if constexpr (point_origin == QP2::point_origin)
return lhs.quantity_ref_from(point_origin) == rhs.quantity_ref_from(QP2::point_origin); return lhs.quantity_ref_from(point_origin) == rhs.quantity_ref_from(QP2::point_origin);
@@ -500,9 +500,9 @@ public:
return lhs - lhs.absolute_point_origin == rhs - rhs.absolute_point_origin; return lhs - lhs.absolute_point_origin == rhs - rhs.absolute_point_origin;
} }
template<QuantityPointOf<absolute_point_origin> QP2> template<std::derived_from<quantity_point> QP, QuantityPointOf<absolute_point_origin> QP2>
requires std::three_way_comparable_with<quantity_type, typename QP2::quantity_type> requires std::three_way_comparable_with<quantity_type, typename QP2::quantity_type>
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP2& rhs) [[nodiscard]] friend constexpr auto operator<=>(const QP& lhs, const QP2& rhs)
{ {
if constexpr (point_origin == QP2::point_origin) if constexpr (point_origin == QP2::point_origin)
return lhs.quantity_ref_from(point_origin) <=> rhs.quantity_ref_from(QP2::point_origin); return lhs.quantity_ref_from(point_origin) <=> rhs.quantity_ref_from(QP2::point_origin);