5 Quantities and units library [quantities]
namespace mp_units {
template<typename T>
concept Quantity = (is-derived-from-specialization-of<T, quantity>());
template<typename Q, auto QS>
concept QuantityOf =
Quantity<Q> && QuantitySpecOf<decltype(auto(Q::quantity_spec)), QS>;
template<Unit UFrom, Unit UTo>
consteval bool integral-conversion-factor(UFrom from, UTo to)
{
return is-integral(get-canonical-unit(from).mag / get-canonical-unit(to).mag);
}
template<typename T>
concept IsFloatingPoint = treat_as_floating_point<T>;
template<typename FromRep, typename ToRep, auto FromUnit = one, auto ToUnit = one>
concept ValuePreservingTo =
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 =
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); };
template<auto QS, typename Func, typename T, typename U>
concept InvokeResultOf =
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 =
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); };
template<typename Func, Quantity Q1, Quantity Q2>
using common-quantity-for =
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 =
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 =
(equivalent(get_unit(R1), get_unit(R2))) && std::convertible_to<Rep1, Rep2>;
template<typename T>
using quantity-like-type =
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>;
template<Reference auto R, RepresentationOf<get_quantity_spec(R)> Rep = double>
class quantity {
public:
Rep numerical-value;
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;
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;
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);
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;
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;
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);
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;
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);
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&);
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);
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>;
}