5 Quantities and units library [quantities]

5.7 Quantity point [qty.pt]

5.7.1 General [qty.pt.general]

Subclause [qty.pt] describes the class template quantity_point that represents the value of a quantity (IEC 60050, 112-01-28) that is an element of an affine space (IEC 60050, 102-03-02,102-04-01).

5.7.2 Point origin [qty.pt.orig]

5.7.2.1 General [qty.pt.orig.general]

This subclause specifies the components for defining the origin of an affine space.
An origin is a point from which measurements (IEC 60050, 112-04-01) take place.

5.7.2.2 Concepts [qty.pt.orig.concepts]

template<typename T> concept PointOrigin = SymbolicConstant<T> && std::derived_from<T, point-origin-interface>; template<typename T, auto QS> concept PointOriginFor = PointOrigin<T> && QuantitySpecOf<decltype(QS), T::quantity-spec>; template<typename T, auto V> concept SameAbsolutePointOriginAs = // exposition only PointOrigin<T> && PointOrigin<decltype(V)> && same-absolute-point-origins(T{}, V);

5.7.2.3 Types [qty.pt.orig.types]

5.7.2.3.1 Absolute [qty.abs.pt.orig]

namespace mp_units { template<QuantitySpec auto QS> struct absolute_point_origin : point-origin-interface { static constexpr QuantitySpec auto quantity-spec = QS; // exposition only }; }
An absolute origin is an origin chosen by convention and not defined in terms of another origin.
A specialization of absolute_point_origin is used as a base type when defining an absolute origin.
QS is the quantity the origin represents.

5.7.2.3.2 Relative [qty.rel.pt.orig]

namespace mp_units { template<QuantityPoint auto QP> struct relative_point_origin : point-origin-interface { static constexpr QuantityPoint auto quantity-point = QP; // exposition only static constexpr QuantitySpec auto quantity-spec = see below; // exposition only static constexpr PointOrigin auto absolute-point-origin = // exposition only QP.absolute_point_origin; }; }
A relative origin is an origin of a subspace (IEC 60050, 102-03-03).
A specialization of relative_point_origin is used as a base type when defining a relative origin O.
O is offset from QP.absolute_point_origin by QP.quantity_from_zero().
The member quantity-spec is equal to QP.point_origin.quantity-spec if QuantityKindSpec<decltype(auto(QP.quantity-spec))> is satisfied, and to QP.quantity-spec otherwise.

5.7.2.3.3 Zeroth [qty.zeroth.pt.orig]

namespace mp_units { template<QuantitySpec auto QS> struct zeroth_point_origin_ final : absolute_point_origin<QS> {}; }
zeroth_point_origin_<QS> represents an origin chosen by convention as the value 0 of the quantity QS.

5.7.2.4 Operations [qty.pt.orig.ops]

namespace mp_units { struct point-origin-interface { template<PointOrigin PO, typename FwdQ, QuantityOf<PO::quantity-spec> Q = std::remove_cvref_t<FwdQ>> friend constexpr quantity_point<Q::reference, PO{}, typename Q::rep> operator+(PO, FwdQ&& q); template<Quantity FwdQ, PointOrigin PO, QuantityOf<PO::quantity-spec> Q = std::remove_cvref_t<FwdQ>> friend constexpr quantity_point<Q::reference, PO{}, typename Q::rep> operator+(FwdQ&& q, PO); template<PointOrigin PO, Quantity Q> requires ReferenceOf<decltype(auto(Q::reference)), PO::quantity-spec> friend constexpr QuantityPoint auto operator-(PO po, const Q& q) requires requires { -q; }; template<PointOrigin PO1, SameAbsolutePointOriginAs<PO1{}> PO2> requires see below friend constexpr Quantity auto operator-(PO1 po1, PO2 po2); template<PointOrigin PO1, PointOrigin PO2> friend consteval bool operator==(PO1 po1, PO2 po2); }; }
template<PointOrigin PO, typename FwdQ, QuantityOf<PO::quantity-spec> Q = std::remove_cvref_t<FwdQ>> friend constexpr quantity_point<Q::reference, PO{}, typename Q::rep> operator+(PO, FwdQ&& q); template<Quantity FwdQ, PointOrigin PO, QuantityOf<PO::quantity-spec> Q = std::remove_cvref_t<FwdQ>> friend constexpr quantity_point<Q::reference, PO{}, typename Q::rep> operator+(FwdQ&& q, PO);
Effects: Equivalent to: return quantity_point{std​::​forward<FwdQ>(q), PO{}};
template<PointOrigin PO, Quantity Q> requires ReferenceOf<decltype(auto(Q::reference)), PO::quantity-spec> friend constexpr QuantityPoint auto operator-(PO po, const Q& q) requires requires { -q; };
Effects: Equivalent to: return po + -q;
template<PointOrigin PO1, SameAbsolutePointOriginAs<PO1{}> PO2> requires see below friend constexpr Quantity auto operator-(PO1 po1, PO2 po2);
Effects: Equivalent to: if constexpr (is-derived-from-specialization-of<PO1, absolute_point_origin>()) { return po1 - po2.quantity-point; } else if constexpr (is-derived-from-specialization-of<PO2, absolute_point_origin>()) { return po1.quantity-point - po2; } else { return po1.quantity-point - po2.quantity-point; }
Remarks: The expression in the requires-clause is equivalent to: QuantitySpecOf<decltype(auto(PO1::quantity-spec)), PO2::quantity-spec> && (is-derived-from-specialization-of<PO1, relative_point_origin>() || is-derived-from-specialization-of<PO2, relative_point_origin>())
template<PointOrigin PO1, PointOrigin PO2> friend consteval bool operator==(PO1 po1, PO2 po2);
Effects: Equivalent to: if constexpr (is-derived-from-specialization-of<PO1, absolute_point_origin>() && is-derived-from-specialization-of<PO2, absolute_point_origin>()) return std::is_same_v<PO1, PO2> || (is-specialization-of<PO1, zeroth_point_origin>() && is-specialization-of<PO2, zeroth_point_origin>() && interconvertible(po1.quantity-spec, po2.quantity-spec)); else if constexpr (is-derived-from-specialization-of<PO1, relative_point_origin>() && is-derived-from-specialization-of<PO2, relative_point_origin>()) return PO1::quantity-point == PO2::quantity-point; else if constexpr (is-derived-from-specialization-of<PO1, relative_point_origin>()) return same-absolute-point-origins(po1, po2) && is_eq_zero(PO1::quantity-point.quantity_from_zero()); else if constexpr (is-derived-from-specialization-of<PO2, relative_point_origin>()) return same-absolute-point-origins(po1, po2) && is_eq_zero(PO2::quantity-point.quantity_from_zero());

5.7.2.5 Utilities [qty.pt.orig.utils]

5.7.2.5.1 Same absolute [qty.same.abs.pt.origs]

template<PointOrigin PO1, PointOrigin PO2> consteval bool same-absolute-point-origins(PO1 po1, PO2 po2); // exposition only
Effects: Equivalent to: if constexpr (is-derived-from-specialization-of<PO1, absolute_point_origin>() && is-derived-from-specialization-of<PO2, absolute_point_origin>()) return po1 == po2; else if constexpr (is-derived-from-specialization-of<PO1, relative_point_origin>() && is-derived-from-specialization-of<PO2, relative_point_origin>()) return po1.absolute-point-origin == po2.absolute-point-origin; else if constexpr (is-derived-from-specialization-of<PO1, relative_point_origin>()) return po1.absolute-point-origin == po2; else if constexpr (is-derived-from-specialization-of<PO2, relative_point_origin>()) return po1 == po2.absolute-point-origin; else return false;

5.7.2.5.2 Default [qty.def.pt.orig]

template<Reference R> consteval PointOriginFor<get_quantity_spec(R{})> auto default_point_origin(R);
Effects: Equivalent to: if constexpr (requires { get_unit(R{}).point-origin; }) return get_unit(R{}).point-origin; else return zeroth_point_origin<get_quantity_spec(R{})>;

5.7.3 Interoperability [qty.pt.like]

template<typename T> concept QuantityPointLike = !QuantityPoint<T> && qty-like-impl<T, quantity_point_like_traits> && // see [qty.like] requires { typename quantity_point<quantity_point_like_traits<T>::reference, quantity_point_like_traits<T>::point_origin, typename quantity_point_like_traits<T>::rep>; };

5.7.4 Class template quantity_point [qty.pt.syn]

namespace mp_units { template<typename T> concept QuantityPoint = (is-derived-from-specialization-of<T, quantity_point>()); template<typename QP, auto V> concept QuantityPointOf = QuantityPoint<QP> && (QuantitySpecOf<decltype(auto(QP::quantity_spec)), V> || SameAbsolutePointOriginAs<decltype(auto(QP::absolute_point_origin)), V>); template<Reference auto R, PointOriginFor<get_quantity_spec(R)> auto PO = default_point_origin(R), RepresentationOf<get_quantity_spec(R)> Rep = double> class quantity_point { public: // member types and values static constexpr Reference auto reference = R; static constexpr QuantitySpec auto quantity_spec = get_quantity_spec(reference); static constexpr Dimension auto dimension = quantity_spec.dimension; static constexpr Unit auto unit = get_unit(reference); static constexpr PointOrigin auto absolute_point_origin = see below; static constexpr PointOrigin auto point_origin = PO; using rep = Rep; using quantity_type = quantity<reference, Rep>; quantity_type quantity-from-origin; // exposition only // [qty.pt.static], static member functions static constexpr quantity_point min() noexcept requires see below; static constexpr quantity_point max() noexcept requires see below; // [qty.pt.cons], constructors and assignment quantity_point() = default; quantity_point(const quantity_point&) = default; quantity_point(quantity_point&&) = default; ~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)) constexpr explicit quantity_point(FwdQ&& q); template<typename FwdQ, QuantityOf<quantity_spec> Q = std::remove_cvref_t<FwdQ>> requires std::constructible_from<quantity_type, FwdQ> constexpr quantity_point(FwdQ&& q, decltype(PO)); template<typename FwdQ, PointOrigin PO2, QuantityOf<PO2::quantity-spec> Q = std::remove_cvref_t<FwdQ>> requires std::constructible_from<quantity_type, FwdQ> && SameAbsolutePointOriginAs<PO2, PO> constexpr quantity_point(FwdQ&& q, PO2); template<QuantityPointOf<absolute_point_origin> QP> requires std::constructible_from<quantity_type, typename QP::quantity_type> constexpr explicit(!std::convertible_to<typename QP::quantity_type, quantity_type>) quantity_point(const QP& qp); template<QuantityPointLike QP> requires see below constexpr explicit(see below) quantity_point(const QP& qp); quantity_point& operator=(const quantity_point&) = default; quantity_point& operator=(quantity_point&&) = default; // [qty.pt.conv], conversions template<SameAbsolutePointOriginAs<absolute_point_origin> NewPO> constexpr QuantityPointOf<(NewPO{})> auto point_for(NewPO new_origin) const; template<UnitCompatibleWith<unit, quantity_spec> ToU> requires see below constexpr QuantityPointOf<quantity_spec> auto in(ToU) const; template<RepresentationOf<quantity_spec> ToRep> requires see below constexpr QuantityPointOf<quantity_spec> auto in() const; template<RepresentationOf<quantity_spec> ToRep, UnitCompatibleWith<unit, quantity_spec> ToU> requires see below constexpr QuantityPointOf<quantity_spec> auto in(ToU) const; template<UnitCompatibleWith<unit, quantity_spec> ToU> requires see below constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const; template<RepresentationOf<quantity_spec> ToRep> requires see below constexpr QuantityPointOf<quantity_spec> auto force_in() const; template<RepresentationOf<quantity_spec> ToRep, UnitCompatibleWith<unit, quantity_spec> ToU> requires see below constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const; // [qty.pt.obs], quantity value observers template<PointOrigin PO2> requires(PO2{} == point_origin) constexpr quantity_type& quantity_ref_from(PO2) & noexcept; template<PointOrigin PO2> requires(PO2{} == point_origin) constexpr const quantity_type& quantity_ref_from(PO2) const & noexcept; template<PointOrigin PO2> requires(PO2{} == point_origin) void quantity_ref_from(PO2) const && = delete; template<PointOrigin PO2> requires requires(const quantity_point qp) { qp - PO2{}; } constexpr Quantity auto quantity_from(PO2) const; template<QuantityPointOf<absolute_point_origin> QP> constexpr Quantity auto quantity_from(const QP&) const; constexpr Quantity auto quantity_from_zero() const; // [qty.pt.conv.ops], conversion operations template<typename QP_, QuantityPointLike QP = std::remove_cvref_t<QP_>> requires see below constexpr explicit(see below) operator QP_() const & noexcept(see below); template<typename QP_, QuantityPointLike QP = std::remove_cvref_t<QP_>> requires see below constexpr explicit(see below) operator QP_() && noexcept(see below); // [qty.pt.unary.ops], unary operations template<Mutable<quantity_point> QP> friend constexpr decltype(auto) operator++(QP&& qp) requires see below; template<Mutable<quantity_point> QP> friend constexpr decltype(auto) operator--(QP&& qp) requires see below; constexpr quantity_point operator++(int) requires see below; constexpr quantity_point operator--(int) requires see below; // [qty.pt.assign.ops], compound assignment operations template<Mutable<quantity_point> QP, auto R2, typename Rep2> requires see below friend constexpr decltype(auto) operator+=(QP&& qp, const quantity<R2, Rep2>& q); template<Mutable<quantity_point> QP, auto R2, typename Rep2> requires see below friend constexpr decltype(auto) operator-=(QP&& qp, const quantity<R2, Rep2>& q); // [qty.pt.arith.ops], arithmetic operations template<std::derived_from<quantity_point> QP, auto R2, typename Rep2> friend constexpr QuantityPoint auto operator+(const QP& qp, const quantity<R2, Rep2>& q) requires see below; template<std::derived_from<quantity_point> QP, auto R2, typename Rep2> friend constexpr QuantityPoint auto operator+(const quantity<R2, Rep2>& q, const QP& qp) requires see below; template<std::derived_from<quantity_point> QP, auto R2, typename Rep2> friend constexpr QuantityPoint auto operator-(const QP& qp, const quantity<R2, Rep2>& q) requires see below; template<std::derived_from<quantity_point> QP, QuantityPointOf<absolute_point_origin> QP2> friend constexpr Quantity auto operator-(const QP& lhs, const QP2& rhs) requires see below; template<std::derived_from<quantity_point> QP, PointOrigin PO2> requires see below friend constexpr Quantity auto operator-(const QP& qp, PO2 po); template<std::derived_from<quantity_point> QP, PointOrigin PO2> requires see below friend constexpr Quantity auto operator-(PO2 po, const QP& qp); // [qty.pt.cmp], comparison template<std::derived_from<quantity_point> QP, QuantityPointOf<absolute_point_origin> QP2> requires see below friend constexpr bool operator==(const QP& lhs, const QP2& rhs); template<std::derived_from<quantity_point> QP, QuantityPointOf<absolute_point_origin> QP2> requires see below friend constexpr auto operator<=>(const QP& lhs, const QP2& rhs); }; template<Quantity Q> explicit quantity_point(Q q) -> quantity_point<Q::reference, default_point_origin(Q::reference), typename Q::rep>; template<Quantity Q, PointOriginFor<Q::quantity_spec> PO> quantity_point(Q, PO) -> quantity_point<Q::reference, PO{}, typename Q::rep>; template<QuantityPointLike QP, typename Traits = quantity_point_like_traits<QP>> explicit(quantity_point_like_traits<QP>::explicit_import) quantity_point(QP) -> quantity_point<Traits::reference, Traits::point_origin, typename Traits::rep>; }
quantity_point<R, PO, Rep> is a structural type (N4971, [temp.param]) if Rep is a structural type.
The member absolute_point_origin is equal to PO if is-derived-from-specialization-of<decltype(PO), absolute_point_origin>() is true, and to PO.quantity-point.absolute_point_origin otherwise.

5.7.5 Static member functions [qty.pt.static]

static constexpr quantity_point min() noexcept requires see below; static constexpr quantity_point max() noexcept requires see below;
Let F be one of min and max.
Returns: {quantity_type​::​F(), PO}.
Remarks: The expression in the requires-clause is equivalent to: requires { quantity_type::F(); }

5.7.6 Constructors [qty.pt.cons]

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)) constexpr explicit quantity_point(FwdQ&& q); template<typename FwdQ, QuantityOf<quantity_spec> Q = std::remove_cvref_t<FwdQ>> requires std::constructible_from<quantity_type, FwdQ> constexpr quantity_point(FwdQ&& q, decltype(PO));
Effects: Initializes quantity-from-origin with std​::​forward<FwdQ>(q).
template<typename FwdQ, PointOrigin PO2, QuantityOf<PO2::quantity-spec> Q = std::remove_cvref_t<FwdQ>> requires std::constructible_from<quantity_type, FwdQ> && SameAbsolutePointOriginAs<PO2, PO> constexpr quantity_point(FwdQ&& q, PO2);
Effects: Equivalent to: quantity_point(quantity_point<Q::reference, PO2{}, typename Q::rep>{std::forward<FwdQ>(q), PO2{}})
template<QuantityPointOf<absolute_point_origin> QP> requires std::constructible_from<quantity_type, typename QP::quantity_type> constexpr explicit(!std::convertible_to<typename QP::quantity_type, quantity_type>) quantity_point(const QP& qp);
Effects: If point_origin == QP​::​point_origin is true, initializes quantity-from-origin with qp.quantity_ref_from(point_origin).
Otherwise, initializes quantity-from-origin with qp - point_origin.
template<QuantityPointLike QP> requires see below constexpr explicit(see below) quantity_point(const QP& qp);
Let Traits be quantity_point_like_traits<QP>.
Effects: Initializes quantity-from-origin with Traits::to_numerical_value(qp), get_unit(Traits::reference)
Remarks: The expression in the requires-clause is equivalent to: (Traits::point_origin == point_origin) && std::convertible_to<quantity<Traits::reference, typename Traits::rep>, quantity_type>
The expression inside explicit is equivalent to: Traits::explicit_import || !std::convertible_to<quantity<Traits::reference, typename Traits::rep>, quantity_type>

5.7.7 Conversions [qty.pt.conv]

template<SameAbsolutePointOriginAs<absolute_point_origin> NewPO> constexpr QuantityPointOf<(NewPO{})> auto point_for(NewPO new_origin) const;
Effects: Equivalent to: if constexpr (std::is_same_v<NewPO, decltype(point_origin)>) return *this; else return ::mp_units::quantity_point{*this - new_origin, new_origin};
template<UnitCompatibleWith<unit, quantity_spec> ToU> requires see below constexpr QuantityPointOf<quantity_spec> auto in(ToU) const; template<RepresentationOf<quantity_spec> ToRep> requires see below constexpr QuantityPointOf<quantity_spec> auto in() const; template<RepresentationOf<quantity_spec> ToRep, UnitCompatibleWith<unit, quantity_spec> ToU> requires see below constexpr QuantityPointOf<quantity_spec> auto in(ToU) const; template<UnitCompatibleWith<unit, quantity_spec> ToU> requires see below constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const; template<RepresentationOf<quantity_spec> ToRep> requires see below constexpr QuantityPointOf<quantity_spec> auto force_in() const; template<RepresentationOf<quantity_spec> ToRep, UnitCompatibleWith<unit, quantity_spec> ToU> requires see below constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const;
Let converted-quantity-expr be an expression denoting the function call to the corresponding member of quantity_ref_from(point_origin).
Effects: Equivalent to: return ::mp_units::quantity_point{converted-quantity-expr, point_origin};
Remarks: The expression in the requires-clause is equivalent to: requires { converted-quantity-expr; }

5.7.8 Quantity value observers [qty.pt.obs]

template<PointOrigin PO2> requires(PO2{} == point_origin) constexpr quantity_type& quantity_ref_from(PO2) & noexcept; template<PointOrigin PO2> requires(PO2{} == point_origin) constexpr const quantity_type& quantity_ref_from(PO2) const & noexcept;
Returns: quantity-from-origin.
template<PointOrigin PO2> requires requires(const quantity_point qp) { qp - PO2{}; } constexpr Quantity auto quantity_from(PO2 rhs) const; template<QuantityPointOf<absolute_point_origin> QP> constexpr Quantity auto quantity_from(const QP& rhs) const;
Effects: Equivalent to: return *this - rhs;
constexpr Quantity auto quantity_from_zero() const;
Effects: Equivalent to: if constexpr (requires { unit.point-origin; }) { // can lose the input unit const auto q = quantity_from(unit.point-origin); if constexpr (requires { q.in(unit); }) // restore the unit return q.in(unit); else return q; } else return quantity_from(absolute_point_origin);

5.7.9 Conversion operations [qty.pt.conv.ops]

template<typename QP_, QuantityPointLike QP = std::remove_cvref_t<QP_>> requires see below constexpr explicit(see below) operator QP_() const & noexcept(see below); template<typename QP_, QuantityPointLike QP = std::remove_cvref_t<QP_>> requires see below constexpr explicit(see below) operator QP_() && noexcept(see below);
Let Traits be quantity_point_like_traits<QP>.
Let result-expr be Traits::from_numerical_value(std::move(quantity-from-origin).numerical-value)
Returns: result-expr.
Remarks: The expression in the requires-clause is equivalent to: (point_origin == Traits::point_origin) && std::convertible_to<quantity_type, quantity<Traits::reference, typename Traits::rep>>
The expression inside explicit is equivalent to: Traits::explicit_export || !std::convertible_to<quantity_type, quantity<Traits::reference, typename Traits::rep>>
Let T be std​::​is_nothrow_copy_constructible_v for the first signature, and std​::​is_nothrow_move_constructible_v for the second signature.
The exception specification is equivalent to: noexcept(result-expr) && T<rep>

5.7.10 Unary operations [qty.pt.unary.ops]

In the following descriptions, let @ be the operator.
template<Mutable<quantity_point> QP> friend constexpr decltype(auto) operator++(QP&& qp) requires see below; template<Mutable<quantity_point> QP> friend constexpr decltype(auto) operator--(QP&& qp) requires see below;
Effects: Equivalent to @qp.quantity-from-origin.
Returns: std​::​forward<QP>(qp).
Remarks: The expression in the requires-clause is equivalent to: requires { @qp.quantity-from-origin; }
constexpr quantity_point operator++(int) requires see below; constexpr quantity_point operator--(int) requires see below;
Effects: Equivalent to: return {quantity-from-origin@, PO};
Remarks: The expression in the requires-clause is equivalent to: requires { quantity-from-origin@; }

5.7.11 Compound assignment operations [qty.pt.assign.ops]

template<Mutable<quantity_point> QP, auto R2, typename Rep2> requires see below friend constexpr decltype(auto) operator+=(QP&& qp, const quantity<R2, Rep2>& q); template<Mutable<quantity_point> QP, auto R2, typename Rep2> requires see below friend constexpr decltype(auto) operator-=(QP&& qp, const quantity<R2, Rep2>& q);
Let @ be the operator.
Effects: Equivalent to qp.quantity-from-origin @ q.
Returns: std​::​forward<QP>(qp).
Remarks: The expression in the requires-clause is equivalent to: QuantityConvertibleTo<quantity<R2, Rep2>, quantity_type> && requires { qp.quantity-from-origin @ q; }

5.7.12 Arithmetic operations [qty.pt.arith.ops]

In the following descriptions, let @ be the operator.
template<std::derived_from<quantity_point> QP, auto R2, typename Rep2> friend constexpr QuantityPoint auto operator+(const QP& qp, const quantity<R2, Rep2>& q) requires see below; template<std::derived_from<quantity_point> QP, auto R2, typename Rep2> friend constexpr QuantityPoint auto operator+(const quantity<R2, Rep2>& q, const QP& qp) requires see below; template<std::derived_from<quantity_point> QP, auto R2, typename Rep2> friend constexpr QuantityPoint auto operator-(const QP& qp, const quantity<R2, Rep2>& q) requires see below;
Effects: Equivalent to: if constexpr (is-specialization-of<PO, zeroth_point_origin>()) return ::mp_units::quantity_point{qp.quantity_ref_from(PO) @ q}; else return ::mp_units::quantity_point{qp.quantity_ref_from(PO) @ q, PO};
Remarks: The expression in the requires-clause is equivalent to: ReferenceOf<decltype(R2), PO.quantity-spec> && requires { qp.quantity_ref_from(PO) @ q; }
template<std::derived_from<quantity_point> QP, QuantityPointOf<absolute_point_origin> QP2> friend constexpr Quantity auto operator-(const QP& lhs, const QP2& rhs) requires see below;
Effects: Equivalent to: return lhs.quantity_ref_from(point_origin) - rhs.quantity_ref_from(QP2::point_origin) + (lhs.point_origin - rhs.point_origin);
Remarks: The expression in the requires-clause is equivalent to: requires { lhs.quantity_ref_from(point_origin) - rhs.quantity_ref_from(QP2::point_origin); }
Recommended practice: The subtraction of two equal origins is not evaluated.
template<std::derived_from<quantity_point> QP, PointOrigin PO2> requires see below friend constexpr Quantity auto operator-(const QP& qp, PO2 po); template<std::derived_from<quantity_point> QP, PointOrigin PO2> requires see below friend constexpr Quantity auto operator-(PO2 po, const QP& qp);
Effects: For the first signature, equivalent to: if constexpr (point_origin == po) return qp.quantity_ref_from(point_origin); else if constexpr (is-derived-from-specialization-of<PO2, ::mp_units::absolute_point_origin>()) { return qp.quantity_ref_from(point_origin) + (qp.point_origin - qp.absolute_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); }
For the second signature, equivalent to: return -(qp - po);
Remarks: The expression in the requires-clause is equivalent to: QuantityPointOf<quantity_point, PO2{}> && ReferenceOf<decltype(auto(reference)), PO2::quantity-spec>
Recommended practice: The subtraction of two equal origins is not evaluated.

5.7.13 Comparison [qty.pt.cmp]

template<std::derived_from<quantity_point> QP, QuantityPointOf<absolute_point_origin> QP2> requires see below friend constexpr bool operator==(const QP& lhs, const QP2& rhs); template<std::derived_from<quantity_point> QP, QuantityPointOf<absolute_point_origin> QP2> requires see below friend constexpr auto operator<=>(const QP& lhs, const QP2& rhs);
Let @ be the operator, and let C be std​::​equality_comparable_with if @ is ==, and std​::​three_way_comparable_with if @ is <=>.
Effects: Equivalent to: return lhs - lhs.absolute_point_origin @ rhs - rhs.absolute_point_origin;
Remarks: The expression in the requires-clause is equivalent to: C<quantity_type, typename QP2::quantity_type>
Recommended practice: If the origins are equal, instead evaluate lhs.quantity_ref_from(point_origin) @ rhs.quantity_ref_from(QP2::point_origin)

5.7.14 Construction helper point [qty.point]

namespace mp_units { template<Reference R> struct point_ { template<typename FwdRep, RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>> constexpr quantity_point<R{}, default_point_origin(R{}), Rep> operator()(FwdRep&& lhs) const; }; }
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{})> Rep = std::remove_cvref_t<FwdRep>> constexpr quantity_point<R{}, default_point_origin(R{}), Rep> operator()(FwdRep&& lhs) const;
Effects: Equivalent to: return quantity_point{quantity{std​::​forward<FwdRep>(lhs), R{}}};

5.7.15 Non-member conversions [qty.pt.non.mem.conv]

template<QuantityPoint ToQP, typename FwdFromQP, QuantityPoint FromQP = std::remove_cvref_t<FwdFromQP>> requires see below constexpr QuantityPoint auto sudo-cast(FwdFromQP&& qp);
Returns: TBD.
value_cast is an explicit cast that allows truncation.
template<Unit auto ToU, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>> requires(convertible(QP::reference, ToU)) constexpr QuantityPoint auto value_cast(FwdQP&& qp);
Effects: Equivalent to: return quantity_point{value_cast<ToU>(std::forward<FwdQP>(qp).quantity-from-origin), QP::point_origin};
template<Representation ToRep, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>> requires RepresentationOf<ToRep, QP::quantity_spec> && std::constructible_from<ToRep, typename QP::rep> constexpr quantity_point<QP::reference, QP::point_origin, ToRep> value_cast(FwdQP&& qp);
Effects: Equivalent to: return {value_cast<ToRep>(std::forward<FwdQP>(qp).quantity-from-origin), QP::point_origin};
template<Unit auto ToU, Representation ToRep, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>> requires see below constexpr QuantityPoint auto value_cast(FwdQP&& qp); template<Representation ToRep, Unit auto ToU, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>> requires see below constexpr QuantityPoint auto value_cast(FwdQP&& qp);
Effects: Equivalent to: return quantity_point{value_cast<ToU, ToRep>(std::forward<FwdQP>(qp).quantity-from-origin), QP::point_origin};
Remarks: The expression in the requires-clause is equivalent to: (convertible(QP::reference, ToU)) && RepresentationOf<ToRep, QP::quantity_spec> && std::constructible_from<ToRep, typename QP::rep>
template<Quantity ToQ, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>> requires(convertible(QP::reference, ToQ::unit)) && (ToQ::quantity_spec == QP::quantity_spec) && std::constructible_from<typename ToQ::rep, typename QP::rep> constexpr QuantityPoint auto value_cast(FwdQP&& qp);
Effects: Equivalent to: return quantity_point{value_cast<ToQ>(std::forward<FwdQP>(qp).quantity-from-origin), QP::point_origin};
template<QuantityPoint ToQP, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>> requires(convertible(QP::reference, ToQP::unit)) && (ToQP::quantity_spec == QP::quantity_spec) && (same-absolute-point-origins(ToQP::point_origin, QP::point_origin)) && std::constructible_from<typename ToQP::rep, typename QP::rep> constexpr QuantityPoint auto value_cast(FwdQP&& qp);
Effects: Equivalent to: return sudo-cast<ToQP>(std​::​forward<FwdQP>(qp));
quantity_cast is an explicit cast that allows converting to more specific quantities.
template<QuantitySpec auto ToQS, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>> requires QuantitySpecCastableTo<QP::quantity_spec, ToQS> constexpr QuantityPoint auto quantity_cast(FwdQP&& qp);
Effects: Equivalent to: return QP{quantity_cast<ToQS>(std::forward<FwdQP>(qp).quantity_from_origin), QP::point_origin};