5 Quantities and units library [quantities]

5.6 Quantity [qty]

5.6.3 Class template quantity [qty.syn]

namespace mp_units { template<typename T> concept Quantity = (is-derived-from-specialization-of<T, quantity>()); // exposition only template<typename Q, auto QS> concept QuantityOf = // exposition only Quantity<Q> && QuantitySpecOf<decltype(auto(Q::quantity_spec)), QS>; template<Unit UFrom, Unit UTo> consteval bool integral-conversion-factor(UFrom from, UTo to) // exposition only { return is-integral(get-canonical-unit(from).mag / get-canonical-unit(to).mag); } template<typename T> concept IsFloatingPoint = treat_as_floating_point<T>; // exposition only template<typename FromRep, typename ToRep, auto FromUnit = one, auto ToUnit = one> concept ValuePreservingTo = // exposition only Representation<std::remove_cvref_t<FromRep>> && Representation<ToRep> && Unit<decltype(FromUnit)> && Unit<decltype(ToUnit)> && std::assignable_from<ToRep&, FromRep> && (IsFloatingPoint<ToRep> || (!IsFloatingPoint<std::remove_cvref_t<FromRep>> && (integral-conversion-factor(FromUnit, ToUnit)))); template<typename QFrom, typename QTo> concept QuantityConvertibleTo = // exposition only Quantity<QFrom> && Quantity<QTo> && QuantitySpecConvertibleTo<QFrom::quantity_spec, QTo::quantity_spec> && UnitConvertibleTo<QFrom::unit, QTo::unit> && ValuePreservingTo<typename QFrom::rep, typename QTo::rep, QFrom::unit, QTo::unit> && requires(QFrom q) { sudo-cast<QTo>(q); }; // see [qty.non.mem.conv] template<auto QS, typename Func, typename T, typename U> concept InvokeResultOf = // exposition only QuantitySpec<decltype(QS)> && std::regular_invocable<Func, T, U> && RepresentationOf<std::invoke_result_t<Func, T, U>, QS>; template<typename Func, typename Q1, typename Q2, auto QS = std::invoke_result_t<Func, decltype(auto(Q1::quantity_spec)), decltype(auto(Q2::quantity_spec))>{}> concept InvocableQuantities = // exposition only QuantitySpec<decltype(QS)> && Quantity<Q1> && Quantity<Q2> && InvokeResultOf<QS, Func, typename Q1::rep, typename Q2::rep>; template<auto R1, auto R2> concept HaveCommonReference = requires { get_common_reference(R1, R2); }; // exposition only template<typename Func, Quantity Q1, Quantity Q2> using common-quantity-for = // exposition only quantity<get_common_reference(Q1::reference, Q2::reference), std::invoke_result_t<Func, typename Q1::rep, typename Q2::rep>>; template<typename Func, typename Q1, typename Q2> concept CommonlyInvocableQuantities = // exposition only Quantity<Q1> && Quantity<Q2> && HaveCommonReference<Q1::reference, Q2::reference> && std::convertible_to<Q1, common-quantity-for<Func, Q1, Q2>> && std::convertible_to<Q2, common-quantity-for<Func, Q1, Q2>> && InvocableQuantities<Func, Q1, Q2, get_common_quantity_spec(Q1::quantity_spec, Q2::quantity_spec)>; template<auto R1, auto R2, typename Rep1, typename Rep2> concept SameValueAs = // exposition only (equivalent(get_unit(R1), get_unit(R2))) && std::convertible_to<Rep1, Rep2>; template<typename T> using quantity-like-type = // exposition only quantity<quantity_like_traits<T>::reference, typename quantity_like_traits<T>::rep>; template<typename T, typename U, typename TT = std::remove_reference_t<T>> concept Mutable = (!std::is_const_v<TT>) && std::derived_from<TT, U>; // exposition only template<Reference auto R, RepresentationOf<get_quantity_spec(R)> Rep = double> class quantity { public: Rep numerical-value; // exposition only // 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); using rep = Rep; // [qty.static], static member functions static constexpr quantity zero() noexcept requires see below; static constexpr quantity one() noexcept requires see below; static constexpr quantity min() noexcept requires see below; static constexpr quantity max() noexcept requires see below; // [qty.cons], constructors and assignment quantity() = default; quantity(const quantity&) = default; quantity(quantity&&) = default; ~quantity() = default; template<typename FwdValue, Reference R2> requires SameValueAs<R2{}, R, std::remove_cvref_t<FwdValue>, Rep> constexpr quantity(FwdValue&& v, R2); template<typename FwdValue, Reference R2, typename Value = std::remove_cvref_t<FwdValue>> requires(!SameValueAs<R2{}, R, Value, Rep>) && QuantityConvertibleTo<quantity<R2{}, Value>, quantity> constexpr quantity(FwdValue&& v, R2); template<ValuePreservingTo<Rep> FwdValue> requires(unit == ::mp_units::one) constexpr quantity(FwdValue&& v); template<QuantityConvertibleTo<quantity> Q> constexpr explicit(see below) quantity(const Q& q); template<QuantityLike Q> requires QuantityConvertibleTo<quantity-like-type<Q>, quantity> constexpr explicit(see below) quantity(const Q& q); quantity& operator=(const quantity&) = default; quantity& operator=(quantity&&) = default; template<ValuePreservingTo<Rep> FwdValue> requires(unit == ::mp_units::one) constexpr quantity& operator=(FwdValue&& v); // [qty.conv], conversions template<UnitCompatibleWith<unit, quantity_spec> ToU> requires QuantityConvertibleTo<quantity, quantity<make-reference(quantity_spec, ToU{}), Rep>> constexpr QuantityOf<quantity_spec> auto in(ToU) const; template<RepresentationOf<quantity_spec> ToRep> requires QuantityConvertibleTo<quantity, quantity<reference, ToRep>> constexpr QuantityOf<quantity_spec> auto in() const; template<RepresentationOf<quantity_spec> ToRep, UnitCompatibleWith<unit, quantity_spec> ToU> requires QuantityConvertibleTo<quantity, quantity<make-reference(quantity_spec, ToU{}), ToRep>> constexpr QuantityOf<quantity_spec> auto in(ToU) const; template<UnitCompatibleWith<unit, quantity_spec> ToU> requires requires(const quantity q) { value_cast<ToU{}>(q); } constexpr QuantityOf<quantity_spec> auto force_in(ToU) const; template<RepresentationOf<quantity_spec> ToRep> requires requires(const quantity q) { value_cast<ToRep>(q); } constexpr QuantityOf<quantity_spec> auto force_in() const; template<RepresentationOf<quantity_spec> ToRep, UnitCompatibleWith<unit, quantity_spec> ToU> requires requires(const quantity q) { value_cast<ToU{}, ToRep>(q); } constexpr QuantityOf<quantity_spec> auto force_in(ToU) const; // [qty.obs], numerical value observers template<Unit U> requires(equivalent(U{}, unit)) constexpr rep& numerical_value_ref_in(U) & noexcept; template<Unit U> requires(equivalent(U{}, unit)) constexpr const rep& numerical_value_ref_in(U) const & noexcept; template<Unit U> requires(equivalent(U{}, unit)) void numerical_value_ref_in(U) const && = delete; template<UnitCompatibleWith<unit, quantity_spec> U> requires QuantityConvertibleTo<quantity, quantity<make-reference(quantity_spec, U{}), Rep>> constexpr rep numerical_value_in(U) const noexcept; template<UnitCompatibleWith<unit, quantity_spec> U> requires requires(const quantity q) { value_cast<U{}>(q); } constexpr rep force_numerical_value_in(U) const noexcept; // [qty.conv.ops], conversion operations template<typename V_, std::constructible_from<Rep> Value = std::remove_cvref_t<V_>> requires(unit == ::mp_units::one) explicit operator V_() const & noexcept; template<typename Q_, QuantityLike Q = std::remove_cvref_t<Q_>> requires QuantityConvertibleTo<quantity, quantity-like-type<Q>> constexpr explicit(see below) operator Q_() const noexcept(see below); // [qty.unary.ops], unary operations constexpr QuantityOf<quantity_spec> auto operator+() const requires see below; constexpr QuantityOf<quantity_spec> auto operator-() const requires see below; template<Mutable<quantity> Q> friend constexpr decltype(auto) operator++(Q&& q) requires see below; template<Mutable<quantity> Q> friend constexpr decltype(auto) operator--(Q&& q) requires see below; constexpr QuantityOf<quantity_spec> auto operator++(int) requires see below; constexpr QuantityOf<quantity_spec> auto operator--(int) requires see below; // [qty.assign.ops], compound assignment operations template<Mutable<quantity> Q, auto R2, typename Rep2> requires see below friend constexpr decltype(auto) operator+=(Q&& lhs, const quantity<R2, Rep2>& rhs); template<Mutable<quantity> Q, auto R2, typename Rep2> requires see below friend constexpr decltype(auto) operator-=(Q&& lhs, const quantity<R2, Rep2>& rhs); template<Mutable<quantity> Q, auto R2, typename Rep2> requires see below friend constexpr decltype(auto) operator%=(Q&& lhs, const quantity<R2, Rep2>& rhs); template<Mutable<quantity> Q, ValuePreservingTo<Rep> Value> requires see below friend constexpr decltype(auto) operator*=(Q&& lhs, const Value& rhs); template<Mutable<quantity> Q, ValuePreservingTo<Rep> Value> requires see below friend constexpr decltype(auto) operator/=(Q&& lhs, const Value& rhs); template<Mutable<quantity> Q, QuantityOf<dimensionless> Q2> requires see below friend constexpr decltype(auto) operator*=(Q&& lhs, const Q2& rhs); template<Mutable<quantity> Q, QuantityOf<dimensionless> Q2> requires see below friend constexpr decltype(auto) operator/=(Q&& lhs, const Q2& rhs); // [qty.arith.ops], arithmetic operations template<std::derived_from<quantity> Q, auto R2, typename Rep2> requires CommonlyInvocableQuantities<std::plus<>, quantity, quantity<R2, Rep2>> friend constexpr Quantity auto operator+(const Q& lhs, const quantity<R2, Rep2>& rhs); template<std::derived_from<quantity> Q, auto R2, typename Rep2> requires CommonlyInvocableQuantities<std::minus<>, quantity, quantity<R2, Rep2>> friend constexpr Quantity auto operator-(const Q& lhs, const quantity<R2, Rep2>& rhs); template<std::derived_from<quantity> Q, auto R2, typename Rep2> requires(!treat_as_floating_point<Rep>) && (!treat_as_floating_point<Rep2>) && CommonlyInvocableQuantities<std::modulus<>, quantity, quantity<R2, Rep2>> friend constexpr Quantity auto operator%(const Q& lhs, const quantity<R2, Rep2>& rhs); template<std::derived_from<quantity> Q, Representation Value> requires(Q::unit == ::mp_units::one) && InvokeResultOf<quantity_spec, std::plus<>, Rep, const Value&> friend constexpr Quantity auto operator+(const Q& lhs, const Value& rhs); template<std::derived_from<quantity> Q, Representation Value> requires(Q::unit == ::mp_units::one) && InvokeResultOf<quantity_spec, std::minus<>, Rep, const Value&> friend constexpr Quantity auto operator-(const Q& lhs, const Value& rhs); template<std::derived_from<quantity> Q, Representation Value> requires(Q::unit == ::mp_units::one) && InvokeResultOf<quantity_spec, std::modulus<>, Rep, const Value&> friend constexpr Quantity auto operator%(const Q& lhs, const Value& rhs); template<std::derived_from<quantity> Q, Representation Value> requires(Q::unit == ::mp_units::one) && InvokeResultOf<quantity_spec, std::plus<>, Rep, const Value&> friend constexpr Quantity auto operator+(const Value& lhs, const Q& rhs); template<std::derived_from<quantity> Q, Representation Value> requires(Q::unit == ::mp_units::one) && InvokeResultOf<quantity_spec, std::minus<>, Rep, const Value&> friend constexpr Quantity auto operator-(const Value& lhs, const Q& rhs); template<std::derived_from<quantity> Q, Representation Value> requires(Q::unit == ::mp_units::one) && InvokeResultOf<quantity_spec, std::modulus<>, Rep, const Value&> friend constexpr Quantity auto operator%(const Value& lhs, const Q& rhs); template<std::derived_from<quantity> Q, auto R2, typename Rep2> requires InvocableQuantities<std::multiplies<>, quantity, quantity<R2, Rep2>> friend constexpr Quantity auto operator*(const Q& lhs, const quantity<R2, Rep2>& rhs); template<std::derived_from<quantity> Q, auto R2, typename Rep2> requires InvocableQuantities<std::divides<>, quantity, quantity<R2, Rep2>> friend constexpr Quantity auto operator/(const Q& lhs, const quantity<R2, Rep2>& rhs); template<std::derived_from<quantity> Q, typename Value> requires(!Quantity<Value>) && (!Reference<Value>) && InvokeResultOf<quantity_spec, std::multiplies<>, Rep, const Value&> friend constexpr QuantityOf<quantity_spec> auto operator*(const Q& lhs, const Value& rhs); template<std::derived_from<quantity> Q, typename Value> requires(!Quantity<Value>) && (!Reference<Value>) && InvokeResultOf<quantity_spec, std::divides<>, Rep, const Value&> friend constexpr QuantityOf<quantity_spec> auto operator/(const Q& lhs, const Value& rhs); template<typename Value, std::derived_from<quantity> Q> requires(!Quantity<Value>) && (!Reference<Value>) && InvokeResultOf<quantity_spec, std::multiplies<>, const Value&, Rep> friend constexpr QuantityOf<quantity_spec> auto operator*(const Value& lhs, const Q& rhs); template<typename Value, std::derived_from<quantity> Q> requires(!Quantity<Value>) && (!Reference<Value>) && InvokeResultOf<quantity_spec, std::divides<>, const Value&, Rep> friend constexpr Quantity auto operator/(const Value&, const Q&); // [qty.cmp], comparison template<std::derived_from<quantity> Q, auto R2, typename Rep2> requires see below friend constexpr bool operator==(const Q& lhs, const quantity<R2, Rep2>& rhs); template<std::derived_from<quantity> Q, auto R2, typename Rep2> requires see below friend constexpr auto operator<=>(const Q& lhs, const quantity<R2, Rep2>& rhs); template<std::derived_from<quantity> Q, Representation Value> requires see below friend constexpr bool operator==(const Q& lhs, const Value& rhs); template<std::derived_from<quantity> Q, Representation Value> requires see below friend constexpr auto operator<=>(const Q& lhs, const Value& rhs); // [qty.val.cmp], value comparison friend constexpr bool is_eq_zero(const quantity& q) requires see below; friend constexpr bool is_neq_zero(const quantity& q) requires see below; friend constexpr bool is_lt_zero(const quantity& q) requires see below; friend constexpr bool is_gt_zero(const quantity& q) requires see below; friend constexpr bool is_lteq_zero(const quantity& q) requires see below; friend constexpr bool is_gteq_zero(const quantity& q) requires see below; }; template<Representation Value, Reference R> quantity(Value, R) -> quantity<R{}, Value>; template<Representation Value> quantity(Value) -> quantity<one, Value>; template<QuantityLike Q> explicit(quantity_like_traits<Q>::explicit_import) quantity(Q) -> quantity<quantity_like_traits<Q>::reference, typename quantity_like_traits<Q>::rep>; }
quantity<R, Rep> is a structural type (N4971, [temp.param]) if Rep is a structural type.