mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-02 11:54:27 +02:00
refactor: binary operators of quantity
and quantity_point
are now hidden friends
This commit is contained in:
@@ -461,6 +461,115 @@ public:
|
|||||||
lhs.numerical_value_is_an_implementation_detail_ /= rhs.numerical_value_is_an_implementation_detail_;
|
lhs.numerical_value_is_an_implementation_detail_ /= rhs.numerical_value_is_an_implementation_detail_;
|
||||||
return std::forward<Q1>(lhs);
|
return std::forward<Q1>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// binary operators on quantities
|
||||||
|
template<auto R2, typename Rep2>
|
||||||
|
requires detail::CommonlyInvocableQuantities<std::plus<>, quantity, quantity<R2, Rep2>>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator+(const quantity& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
|
{
|
||||||
|
using ret = detail::common_quantity_for<std::plus<>, quantity, quantity<R2, Rep2>>;
|
||||||
|
const ret ret_lhs(lhs);
|
||||||
|
const ret ret_rhs(rhs);
|
||||||
|
return ::mp_units::quantity{ret_lhs.numerical_value_ref_in(ret::unit) + ret_rhs.numerical_value_ref_in(ret::unit),
|
||||||
|
ret::reference};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<auto R2, typename Rep2>
|
||||||
|
requires detail::CommonlyInvocableQuantities<std::minus<>, quantity, quantity<R2, Rep2>>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
|
{
|
||||||
|
using ret = detail::common_quantity_for<std::minus<>, quantity, quantity<R2, Rep2>>;
|
||||||
|
const ret ret_lhs(lhs);
|
||||||
|
const ret ret_rhs(rhs);
|
||||||
|
return ::mp_units::quantity{ret_lhs.numerical_value_ref_in(ret::unit) - ret_rhs.numerical_value_ref_in(ret::unit),
|
||||||
|
ret::reference};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<auto R2, typename Rep2>
|
||||||
|
requires(!treat_as_floating_point<Rep>) && (!treat_as_floating_point<Rep2>) &&
|
||||||
|
detail::CommonlyInvocableQuantities<std::modulus<>, quantity, quantity<R2, Rep2>>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
|
{
|
||||||
|
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
|
||||||
|
using ret = detail::common_quantity_for<std::modulus<>, quantity, quantity<R2, Rep2>>;
|
||||||
|
const ret ret_lhs(lhs);
|
||||||
|
const ret ret_rhs(rhs);
|
||||||
|
return ::mp_units::quantity{ret_lhs.numerical_value_ref_in(ret::unit) % ret_rhs.numerical_value_ref_in(ret::unit),
|
||||||
|
ret::reference};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<auto R2, typename Rep2>
|
||||||
|
requires detail::InvocableQuantities<std::multiplies<>, quantity, quantity<R2, Rep2>>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator*(const quantity& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
|
{
|
||||||
|
return ::mp_units::quantity{lhs.numerical_value_ref_in(get_unit(R)) * rhs.numerical_value_ref_in(get_unit(R2)),
|
||||||
|
R * R2};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Value>
|
||||||
|
requires(!Quantity<Value>) && (!Reference<Value>) &&
|
||||||
|
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, Rep, const Value&>
|
||||||
|
[[nodiscard]] friend constexpr QuantityOf<get_quantity_spec(R)> auto operator*(const quantity& q, const Value& v)
|
||||||
|
{
|
||||||
|
return ::mp_units::quantity{q.numerical_value_ref_in(get_unit(R)) * v, R};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Value>
|
||||||
|
requires(!Quantity<Value>) && (!Reference<Value>) &&
|
||||||
|
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, const Value&, Rep>
|
||||||
|
[[nodiscard]] friend constexpr QuantityOf<get_quantity_spec(R)> auto operator*(const Value& v, const quantity& q)
|
||||||
|
{
|
||||||
|
return ::mp_units::quantity{v * q.numerical_value_ref_in(get_unit(R)), R};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<auto R2, typename Rep2>
|
||||||
|
requires detail::InvocableQuantities<std::divides<>, quantity, quantity<R2, Rep2>>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator/(const quantity& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
|
{
|
||||||
|
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
|
||||||
|
return ::mp_units::quantity{lhs.numerical_value_ref_in(get_unit(R)) / rhs.numerical_value_ref_in(get_unit(R2)),
|
||||||
|
R / R2};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Value>
|
||||||
|
requires(!Quantity<Value>) && (!Reference<Value>) &&
|
||||||
|
detail::InvokeResultOf<get_quantity_spec(R).character, std::divides<>, Rep, const Value&>
|
||||||
|
[[nodiscard]] friend constexpr QuantityOf<get_quantity_spec(R)> auto operator/(const quantity& q, const Value& v)
|
||||||
|
{
|
||||||
|
MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero());
|
||||||
|
return ::mp_units::quantity{q.numerical_value_ref_in(get_unit(R)) / v, R};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Value>
|
||||||
|
requires(!Quantity<Value>) && (!Reference<Value>) &&
|
||||||
|
detail::InvokeResultOf<get_quantity_spec(R).character, std::divides<>, const Value&, Rep>
|
||||||
|
[[nodiscard]] friend constexpr QuantityOf<inverse(get_quantity_spec(R))> auto operator/(const Value& v,
|
||||||
|
const quantity& q)
|
||||||
|
{
|
||||||
|
return ::mp_units::quantity{v / q.numerical_value_ref_in(get_unit(R)), ::mp_units::one / R};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<auto R2, typename 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>
|
||||||
|
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
|
{
|
||||||
|
using ct = std::common_type_t<quantity, quantity<R2, Rep2>>;
|
||||||
|
const ct ct_lhs(lhs);
|
||||||
|
const ct ct_rhs(rhs);
|
||||||
|
return ct_lhs.numerical_value_ref_in(ct::unit) == ct_rhs.numerical_value_ref_in(ct::unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<auto R2, typename 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>
|
||||||
|
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
|
{
|
||||||
|
using ct = std::common_type_t<quantity, quantity<R2, Rep2>>;
|
||||||
|
const ct ct_lhs(lhs);
|
||||||
|
const ct ct_rhs(rhs);
|
||||||
|
return ct_lhs.numerical_value_ref_in(ct::unit) <=> ct_rhs.numerical_value_ref_in(ct::unit);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// CTAD
|
// CTAD
|
||||||
@@ -473,113 +582,6 @@ explicit(
|
|||||||
is_specialization_of<decltype(quantity_like_traits<Q>::to_numerical_value(std::declval<Q>())), convert_explicitly>)
|
is_specialization_of<decltype(quantity_like_traits<Q>::to_numerical_value(std::declval<Q>())), convert_explicitly>)
|
||||||
quantity(Q) -> quantity<quantity_like_traits<Q>::reference, typename quantity_like_traits<Q>::rep>;
|
quantity(Q) -> quantity<quantity_like_traits<Q>::reference, typename quantity_like_traits<Q>::rep>;
|
||||||
|
|
||||||
// binary operators on quantities
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|
||||||
requires detail::CommonlyInvocableQuantities<std::plus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator+(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
|
||||||
{
|
|
||||||
using ret = detail::common_quantity_for<std::plus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
|
||||||
const ret ret_lhs(lhs);
|
|
||||||
const ret ret_rhs(rhs);
|
|
||||||
return quantity{ret_lhs.numerical_value_ref_in(ret::unit) + ret_rhs.numerical_value_ref_in(ret::unit),
|
|
||||||
ret::reference};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|
||||||
requires detail::CommonlyInvocableQuantities<std::minus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator-(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
|
||||||
{
|
|
||||||
using ret = detail::common_quantity_for<std::minus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
|
||||||
const ret ret_lhs(lhs);
|
|
||||||
const ret ret_rhs(rhs);
|
|
||||||
return quantity{ret_lhs.numerical_value_ref_in(ret::unit) - ret_rhs.numerical_value_ref_in(ret::unit),
|
|
||||||
ret::reference};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|
||||||
requires(!treat_as_floating_point<Rep1>) && (!treat_as_floating_point<Rep2>) &&
|
|
||||||
detail::CommonlyInvocableQuantities<std::modulus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator%(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
|
||||||
{
|
|
||||||
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
|
|
||||||
using ret = detail::common_quantity_for<std::modulus<>, quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
|
||||||
const ret ret_lhs(lhs);
|
|
||||||
const ret ret_rhs(rhs);
|
|
||||||
return quantity{ret_lhs.numerical_value_ref_in(ret::unit) % ret_rhs.numerical_value_ref_in(ret::unit),
|
|
||||||
ret::reference};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|
||||||
requires detail::InvocableQuantities<std::multiplies<>, quantity<R1, Rep1>, quantity<R2, Rep2>>
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator*(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
|
||||||
{
|
|
||||||
return quantity{lhs.numerical_value_ref_in(get_unit(R1)) * rhs.numerical_value_ref_in(get_unit(R2)), R1 * R2};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto R, typename Rep, typename Value>
|
|
||||||
requires(!Quantity<Value>) && (!Reference<Value>) &&
|
|
||||||
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, Rep, const Value&>
|
|
||||||
[[nodiscard]] constexpr QuantityOf<get_quantity_spec(R)> auto operator*(const quantity<R, Rep>& q, const Value& v)
|
|
||||||
{
|
|
||||||
return quantity{q.numerical_value_ref_in(get_unit(R)) * v, R};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Value, auto R, typename Rep>
|
|
||||||
requires(!Quantity<Value>) && (!Reference<Value>) &&
|
|
||||||
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, const Value&, Rep>
|
|
||||||
[[nodiscard]] constexpr QuantityOf<get_quantity_spec(R)> auto operator*(const Value& v, const quantity<R, Rep>& q)
|
|
||||||
{
|
|
||||||
return quantity{v * q.numerical_value_ref_in(get_unit(R)), R};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|
||||||
requires detail::InvocableQuantities<std::divides<>, quantity<R1, Rep1>, quantity<R2, Rep2>>
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator/(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
|
||||||
{
|
|
||||||
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
|
|
||||||
return quantity{lhs.numerical_value_ref_in(get_unit(R1)) / rhs.numerical_value_ref_in(get_unit(R2)), R1 / R2};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto R, typename Rep, typename Value>
|
|
||||||
requires(!Quantity<Value>) && (!Reference<Value>) &&
|
|
||||||
detail::InvokeResultOf<get_quantity_spec(R).character, std::divides<>, Rep, const Value&>
|
|
||||||
[[nodiscard]] constexpr QuantityOf<get_quantity_spec(R)> auto operator/(const quantity<R, Rep>& q, const Value& v)
|
|
||||||
{
|
|
||||||
MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero());
|
|
||||||
return quantity{q.numerical_value_ref_in(get_unit(R)) / v, R};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Value, auto R, typename Rep>
|
|
||||||
requires(!Quantity<Value>) && (!Reference<Value>) &&
|
|
||||||
detail::InvokeResultOf<get_quantity_spec(R).character, std::divides<>, const Value&, Rep>
|
|
||||||
[[nodiscard]] constexpr QuantityOf<inverse(get_quantity_spec(R))> auto operator/(const Value& v,
|
|
||||||
const quantity<R, Rep>& q)
|
|
||||||
{
|
|
||||||
return quantity{v / q.numerical_value_ref_in(get_unit(R)), ::mp_units::one / R};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|
||||||
requires requires { typename std::common_type_t<quantity<R1, Rep1>, quantity<R2, Rep2>>; } &&
|
|
||||||
std::equality_comparable<typename std::common_type_t<quantity<R1, Rep1>, quantity<R2, Rep2>>::rep>
|
|
||||||
[[nodiscard]] constexpr bool operator==(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
|
||||||
{
|
|
||||||
using ct = std::common_type_t<quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
|
||||||
const ct ct_lhs(lhs);
|
|
||||||
const ct ct_rhs(rhs);
|
|
||||||
return ct_lhs.numerical_value_ref_in(ct::unit) == ct_rhs.numerical_value_ref_in(ct::unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|
||||||
requires requires { typename std::common_type_t<quantity<R1, Rep1>, quantity<R2, Rep2>>; } &&
|
|
||||||
std::three_way_comparable<typename std::common_type_t<quantity<R1, Rep1>, quantity<R2, Rep2>>::rep>
|
|
||||||
[[nodiscard]] constexpr auto operator<=>(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
|
|
||||||
{
|
|
||||||
using ct = std::common_type_t<quantity<R1, Rep1>, quantity<R2, Rep2>>;
|
|
||||||
const ct ct_lhs(lhs);
|
|
||||||
const ct ct_rhs(rhs);
|
|
||||||
return ct_lhs.numerical_value_ref_in(ct::unit) <=> ct_rhs.numerical_value_ref_in(ct::unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
MP_UNITS_EXPORT_END
|
MP_UNITS_EXPORT_END
|
||||||
|
|
||||||
} // namespace mp_units
|
} // namespace mp_units
|
||||||
|
@@ -413,6 +413,102 @@ public:
|
|||||||
qp.quantity_from_origin_is_an_implementation_detail_ -= q;
|
qp.quantity_from_origin_is_an_implementation_detail_ -= q;
|
||||||
return std::forward<QP>(qp);
|
return std::forward<QP>(qp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// binary operators on quantity points
|
||||||
|
template<auto R2, typename Rep2>
|
||||||
|
// TODO simplify when gcc catches up
|
||||||
|
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)
|
||||||
|
requires requires { qp.quantity_ref_from(PO) + q; }
|
||||||
|
{
|
||||||
|
if constexpr (detail::is_zeroth_point_origin(PO))
|
||||||
|
return ::mp_units::quantity_point{qp.quantity_ref_from(PO) + q};
|
||||||
|
else
|
||||||
|
return ::mp_units::quantity_point{qp.quantity_ref_from(PO) + q, PO};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<auto R1, typename Rep1>
|
||||||
|
// TODO simplify when gcc catches up
|
||||||
|
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)
|
||||||
|
requires requires { q + qp.quantity_ref_from(PO); }
|
||||||
|
{
|
||||||
|
return qp + q;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<auto R2, typename Rep2>
|
||||||
|
// TODO simplify when gcc catches up
|
||||||
|
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)
|
||||||
|
requires requires { qp.quantity_ref_from(PO) - q; }
|
||||||
|
{
|
||||||
|
if constexpr (detail::is_zeroth_point_origin(PO))
|
||||||
|
return ::mp_units::quantity_point{qp.quantity_ref_from(PO) - q};
|
||||||
|
else
|
||||||
|
return ::mp_units::quantity_point{qp.quantity_ref_from(PO) - q, PO};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<QuantityPointOf<absolute_point_origin> QP2>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity_point& lhs, const QP2& rhs)
|
||||||
|
// TODO consider constraining it for both branches
|
||||||
|
requires requires { lhs.quantity_ref_from(point_origin) - rhs.quantity_ref_from(QP2::point_origin); }
|
||||||
|
{
|
||||||
|
if constexpr (point_origin == QP2::point_origin)
|
||||||
|
return lhs.quantity_ref_from(point_origin) - rhs.quantity_ref_from(QP2::point_origin);
|
||||||
|
else
|
||||||
|
return lhs.quantity_ref_from(point_origin) - rhs.quantity_ref_from(QP2::point_origin) +
|
||||||
|
(lhs.point_origin - rhs.point_origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<PointOrigin PO2>
|
||||||
|
requires QuantityPointOf<quantity_point, PO2{}> &&
|
||||||
|
ReferenceOf<std::remove_const_t<decltype(reference)>, PO2::quantity_spec>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity_point& qp, PO2 po)
|
||||||
|
{
|
||||||
|
if constexpr (point_origin == po)
|
||||||
|
return qp.quantity_ref_from(point_origin);
|
||||||
|
else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<PO2>) {
|
||||||
|
if constexpr (point_origin == absolute_point_origin)
|
||||||
|
return qp.quantity_ref_from(point_origin);
|
||||||
|
else
|
||||||
|
return qp.quantity_ref_from(point_origin) + (qp.point_origin - qp.absolute_point_origin);
|
||||||
|
} else {
|
||||||
|
if constexpr (point_origin == po.quantity_point.point_origin)
|
||||||
|
return qp.quantity_ref_from(point_origin) - po.quantity_point.quantity_ref_from(po.quantity_point.point_origin);
|
||||||
|
else
|
||||||
|
return qp.quantity_ref_from(point_origin) -
|
||||||
|
po.quantity_point.quantity_ref_from(po.quantity_point.point_origin) +
|
||||||
|
(qp.point_origin - po.quantity_point.point_origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<PointOrigin PO1>
|
||||||
|
requires QuantityPointOf<quantity_point, PO1{}> &&
|
||||||
|
ReferenceOf<std::remove_const_t<decltype(reference)>, PO1::quantity_spec>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator-(PO1 po, const quantity_point& qp)
|
||||||
|
{
|
||||||
|
return -(qp - po);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<QuantityPointOf<absolute_point_origin> QP2>
|
||||||
|
requires std::equality_comparable_with<quantity_type, typename QP2::quantity_type>
|
||||||
|
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP2& rhs)
|
||||||
|
{
|
||||||
|
if constexpr (point_origin == QP2::point_origin)
|
||||||
|
return lhs.quantity_ref_from(point_origin) == rhs.quantity_ref_from(QP2::point_origin);
|
||||||
|
else
|
||||||
|
return lhs - lhs.absolute_point_origin == rhs - rhs.absolute_point_origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<QuantityPointOf<absolute_point_origin> QP2>
|
||||||
|
requires std::three_way_comparable_with<quantity_type, typename QP2::quantity_type>
|
||||||
|
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP2& rhs)
|
||||||
|
{
|
||||||
|
if constexpr (point_origin == QP2::point_origin)
|
||||||
|
return lhs.quantity_ref_from(point_origin) <=> rhs.quantity_ref_from(QP2::point_origin);
|
||||||
|
else
|
||||||
|
return lhs - lhs.absolute_point_origin <=> rhs - rhs.absolute_point_origin;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// CTAD
|
// CTAD
|
||||||
@@ -428,29 +524,7 @@ explicit(is_specialization_of<decltype(quantity_point_like_traits<QP>::to_numeri
|
|||||||
-> quantity_point<quantity_point_like_traits<QP>::reference, quantity_point_like_traits<QP>::point_origin,
|
-> quantity_point<quantity_point_like_traits<QP>::reference, quantity_point_like_traits<QP>::point_origin,
|
||||||
typename quantity_point_like_traits<QP>::rep>;
|
typename quantity_point_like_traits<QP>::rep>;
|
||||||
|
|
||||||
template<auto R1, auto PO1, typename Rep1, auto R2, typename Rep2>
|
// binary operators on point origins
|
||||||
// TODO simplify when gcc catches up
|
|
||||||
requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R2)), PO1.quantity_spec>
|
|
||||||
[[nodiscard]] constexpr QuantityPoint auto operator+(const quantity_point<R1, PO1, Rep1>& qp,
|
|
||||||
const quantity<R2, Rep2>& q)
|
|
||||||
requires requires { qp.quantity_ref_from(PO1) + q; }
|
|
||||||
{
|
|
||||||
if constexpr (detail::is_zeroth_point_origin(PO1))
|
|
||||||
return quantity_point{qp.quantity_ref_from(PO1) + q};
|
|
||||||
else
|
|
||||||
return quantity_point{qp.quantity_ref_from(PO1) + q, PO1};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto R1, typename Rep1, auto R2, auto PO2, typename Rep2>
|
|
||||||
// TODO simplify when gcc catches up
|
|
||||||
requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R1)), PO2.quantity_spec>
|
|
||||||
[[nodiscard]] constexpr QuantityPoint auto operator+(const quantity<R1, Rep1>& q,
|
|
||||||
const quantity_point<R2, PO2, Rep2>& qp)
|
|
||||||
requires requires { q + qp.quantity_ref_from(PO2); }
|
|
||||||
{
|
|
||||||
return qp + q;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<PointOrigin PO, Quantity Q>
|
template<PointOrigin PO, Quantity Q>
|
||||||
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO::quantity_spec>
|
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO::quantity_spec>
|
||||||
[[nodiscard]] constexpr quantity_point<Q::reference, PO{}, typename Q::rep> operator+(PO, Q&& q)
|
[[nodiscard]] constexpr quantity_point<Q::reference, PO{}, typename Q::rep> operator+(PO, Q&& q)
|
||||||
@@ -465,19 +539,6 @@ template<Quantity Q, PointOrigin PO>
|
|||||||
return po + std::forward<Q>(q);
|
return po + std::forward<Q>(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto R1, auto PO1, typename Rep1, auto R2, typename Rep2>
|
|
||||||
// TODO simplify when gcc catches up
|
|
||||||
requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R2)), PO1.quantity_spec>
|
|
||||||
[[nodiscard]] constexpr QuantityPoint auto operator-(const quantity_point<R1, PO1, Rep1>& qp,
|
|
||||||
const quantity<R2, Rep2>& q)
|
|
||||||
requires requires { qp.quantity_ref_from(PO1) - q; }
|
|
||||||
{
|
|
||||||
if constexpr (detail::is_zeroth_point_origin(PO1))
|
|
||||||
return quantity_point{qp.quantity_ref_from(PO1) - q};
|
|
||||||
else
|
|
||||||
return quantity_point{qp.quantity_ref_from(PO1) - q, PO1};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<PointOrigin PO, Quantity Q>
|
template<PointOrigin PO, Quantity Q>
|
||||||
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO::quantity_spec>
|
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO::quantity_spec>
|
||||||
[[nodiscard]] constexpr QuantityPoint auto operator-(PO po, const Q& q)
|
[[nodiscard]] constexpr QuantityPoint auto operator-(PO po, const Q& q)
|
||||||
@@ -486,47 +547,6 @@ template<PointOrigin PO, Quantity Q>
|
|||||||
return po + (-q);
|
return po + (-q);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator-(const QP1& lhs, const QP2& rhs)
|
|
||||||
// TODO consider constraining it for both branches
|
|
||||||
requires requires { lhs.quantity_ref_from(QP1::point_origin) - rhs.quantity_ref_from(QP2::point_origin); }
|
|
||||||
{
|
|
||||||
if constexpr (QP1::point_origin == QP2::point_origin)
|
|
||||||
return lhs.quantity_ref_from(QP1::point_origin) - rhs.quantity_ref_from(QP2::point_origin);
|
|
||||||
else
|
|
||||||
return lhs.quantity_ref_from(QP1::point_origin) - rhs.quantity_ref_from(QP2::point_origin) +
|
|
||||||
(lhs.point_origin - rhs.point_origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<PointOrigin PO, QuantityPointOf<PO{}> QP>
|
|
||||||
requires ReferenceOf<std::remove_const_t<decltype(QP::reference)>, PO::quantity_spec>
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator-(const QP& qp, PO po)
|
|
||||||
{
|
|
||||||
if constexpr (QP::point_origin == po)
|
|
||||||
return qp.quantity_ref_from(QP::point_origin);
|
|
||||||
else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<PO>) {
|
|
||||||
if constexpr (QP::point_origin == QP::absolute_point_origin)
|
|
||||||
return qp.quantity_ref_from(QP::point_origin);
|
|
||||||
else
|
|
||||||
return qp.quantity_ref_from(QP::point_origin) + (qp.point_origin - qp.absolute_point_origin);
|
|
||||||
} else {
|
|
||||||
if constexpr (QP::point_origin == po.quantity_point.point_origin)
|
|
||||||
return qp.quantity_ref_from(QP::point_origin) -
|
|
||||||
po.quantity_point.quantity_ref_from(po.quantity_point.point_origin);
|
|
||||||
else
|
|
||||||
return qp.quantity_ref_from(QP::point_origin) -
|
|
||||||
po.quantity_point.quantity_ref_from(po.quantity_point.point_origin) +
|
|
||||||
(qp.point_origin - po.quantity_point.point_origin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<PointOrigin PO, QuantityPointOf<PO{}> QP>
|
|
||||||
requires ReferenceOf<std::remove_const_t<decltype(QP::reference)>, PO::quantity_spec>
|
|
||||||
[[nodiscard]] constexpr Quantity auto operator-(PO po, const QP& qp)
|
|
||||||
{
|
|
||||||
return -(qp - po);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<PointOrigin PO1, detail::SameAbsolutePointOriginAs<PO1{}> PO2>
|
template<PointOrigin PO1, detail::SameAbsolutePointOriginAs<PO1{}> PO2>
|
||||||
requires QuantitySpecOf<std::remove_const_t<decltype(PO1::quantity_spec)>, PO2::quantity_spec> &&
|
requires QuantitySpecOf<std::remove_const_t<decltype(PO1::quantity_spec)>, PO2::quantity_spec> &&
|
||||||
(detail::is_derived_from_specialization_of_relative_point_origin<PO1> ||
|
(detail::is_derived_from_specialization_of_relative_point_origin<PO1> ||
|
||||||
@@ -542,26 +562,6 @@ template<PointOrigin PO1, detail::SameAbsolutePointOriginAs<PO1{}> PO2>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
|
|
||||||
requires std::three_way_comparable_with<typename QP1::quantity_type, typename QP2::quantity_type>
|
|
||||||
[[nodiscard]] constexpr auto operator<=>(const QP1& lhs, const QP2& rhs)
|
|
||||||
{
|
|
||||||
if constexpr (QP1::point_origin == QP2::point_origin)
|
|
||||||
return lhs.quantity_ref_from(QP1::point_origin) <=> rhs.quantity_ref_from(QP2::point_origin);
|
|
||||||
else
|
|
||||||
return lhs - lhs.absolute_point_origin <=> rhs - rhs.absolute_point_origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
|
|
||||||
requires std::equality_comparable_with<typename QP1::quantity_type, typename QP2::quantity_type>
|
|
||||||
[[nodiscard]] constexpr bool operator==(const QP1& lhs, const QP2& rhs)
|
|
||||||
{
|
|
||||||
if constexpr (QP1::point_origin == QP2::point_origin)
|
|
||||||
return lhs.quantity_ref_from(QP1::point_origin) == rhs.quantity_ref_from(QP2::point_origin);
|
|
||||||
else
|
|
||||||
return lhs - lhs.absolute_point_origin == rhs - rhs.absolute_point_origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
MP_UNITS_EXPORT_END
|
MP_UNITS_EXPORT_END
|
||||||
|
|
||||||
} // namespace mp_units
|
} // namespace mp_units
|
||||||
|
Reference in New Issue
Block a user