Quantity

Dimensioned quantity with compile-time unit checking/conversion

Context

_images/ditaa-8403fa66acef33ca91cef45ab20b9810035d93a5.png
#include <xo/unit/quantity.hpp>

allowmixing

object qty1<<quantity>>
qty1 : scale = 1.23

rectangle constexpr #e0f0ff {

object unit<<scaled_unit>>
unit : is_natural() = true

qty1 o-- unit : s_scaled_unit (static constexpr)

}

  • Arithmetic on xo::qty::quantity instances does not use xo::qty::quantity::s_scaled_unit at runtime; instead gets everything it needs at compile time.

  • The xo::qty::quantity template takes a xo::qty::scaled_unit instance, but only accepts values with xo::qty::scaled_unit::is_natural() == true.

    This accomodation (instead of requiring a xo::qty::natural_unit instance is to make possible code like this possible:

    #include "xo/unit/quantity.hpp"
    
    using namespace xo::qty;
    
    quantity<u::meter / u::second> x;
    quantity<u::meter * u::mter> y;
    

    while rejecting attempt to mix multiple scales in the same quantity value:

    quantity<u::meter * u::millimeter> x; // will not compile
    

Class

The primary data structure for interacting with xo-unit is the template class xo::qty::quantity. A quantity is a compile-time wrapper around a single arithmetic value, with type taken from the Repr parameter in quantity<Unit, Repr>.

template<auto ScaledUnit, typename Repr = double>
class quantity

represent a scalar quantity with associated units.

Enforce dimensional consistency at compile time. sizeof(quantity) == sizeof(Repr).

Unit information is associated with type, not value. A quantity’s runtime state consists of exactly one Repr instance:

sizeof(quantity<NaturalUnit, Repr>) == sizeof(Repr)

Template Parameters:
  • ScaledUnit – is a non-type template paramoeter identifying a unit used for this quantity. In xo-unit it will be an instance of natural_unit

  • Repr – is a type used to represent a multiple of ScaledUnit.

Member Variables

group Quantity-static-vars

Variables

static scaled_unit<ratio_int_type> s_scaled_unit = ScaledUnit

unit for quantity of this type. Determined at compile-time

group Quantity-instance-vars

Variables

Repr scale_ = Repr{}

quantity represents this multiple of s_scaled_unit

Public to avoid disqualifying quantity as a ‘structural type’; prerequisite for using a quantity instance as a non-type template parameter

Type Traits

group quantity type traits

Typedefs

using repr_type = Repr

runtime representation for value of this type

using unit_type = decltype(ScaledUnit)

type used to represent unit information

using ratio_int_type = unit_type::ratio_int_type

type used for numerator and denominator in basis-unit scalefactor ratios

using ratio_int2x_type = detail::width2x_t<typename unit_type::ratio_int_type>

double-width type used for numerator and denominator of intermediate scalefactor ratios. Used to mitigate loss of precision during computation of conversion factors between units with widely-differing magnitude

Constructors

group quantity constructors

Functions

inline constexpr quantity()

create a zero amount with dimension ScaledUnit

inline explicit constexpr quantity(Repr scale)

create a quantity representing scale ScaledUnits

constexpr quantity(const quantity&) = default

copy constructor

The simplest way to create a quantity instance is to use either

Assignment

group quantity assignment operators

Functions

inline quantity &operator=(const quantity &x)

assignment from quantity with identical units

template<typename Q2>
inline quantity &operator=(const Q2 &x)

assignment from quantity with compatible units

Access Methods

group quantity access methods

Functions

inline const repr_type &scale() const

value of scale_ in quantity representing amount (scale_ * s_unit)

inline const unit_type &unit() const

s_unit in quantity representing amount (scale_ * s_unit)

inline bool is_negative() const

true iff this quantity is strictly negative

inline bool is_positive() const

true iff this quantity is strictly positive

static inline bool is_dimensionless()

true iff this quantity represents a dimensionless value

inline nu_abbrev_type abbrev() const

abbreviated suffix for quantities with this unit

Constants

group static quantity constants

Variables

static bool always_constexpr_unit = true

Use to distinguish quantity from xquantity instances.

Useful in c++ template resolution.

Conversion Methods

Amount-preserving conversion to quantities with different units and/or representation.

group Quantity-unit-conversion

Functions

template<typename Repr2>
inline auto with_repr() const

create equivalent quantity using scale representation Repr2 instead of Repr

template<natural_unit<ratio_int_type> NaturalUnit2>
inline auto rescale() const

create equivalent quantity expressed as a multiple of NaturalUnit2 instead of s_unit

template<scaled_unit<ratio_int_type> ScaledUnit2>
inline auto rescale_ext() const

create equivalent quantity expressed as as multiple of ScaledUnit2 instead of s_unit

template<typename Q2>
inline constexpr operator Q2() const
inline constexpr operator Repr() const

For dimensionless quantities: convert to underlying scale value

Not present for dimensioned quantities.

Arithmetic

group Quantity-operators

Functions

inline quantity operator-() const

unary negation; preserves unit information

template<typename Quantity2>
inline quantity &operator+=(const Quantity2 &y)

add y in-place, converting units if necessary

template<typename Quantity2>
inline quantity &operator-=(const Quantity2 &y)

subtract y in-place, converting units if necessary

template<typename Dimensionless>
inline quantity &operator*=(Dimensionless y)

multiply y in-place. y must be dimensionless

template<typename Dimensionless>
inline quantity &operator/=(Dimensionless y)

divide y in-place. y must be dimensionless

template<typename Q1, typename Q2>
auto operator*(const Q1 &x, const Q2 &y)

note: won’t have constexpr result w/ fractional dimension until c++26 (when sqrt(), pow() are constexpr)

note: won’t have constexpr result until c++26 (when sqrt(), pow() are constexpr)

template<typename Dimensionless, typename Quantity>
auto operator*(const Quantity &x, Dimensionless y)

note: does not require unit scaling, so constexpr with c++23

template<typename Dimensionless, typename Quantity>
auto operator*(Dimensionless x, const Quantity &y)

note: does not require unit scaling, so constexpr with c++23

template<typename Q1, typename Q2>
auto operator/(const Q1 &x, const Q2 &y)

divide quantity x by quantity y.

note: won’t have constexpr result w/ fractional dimension until c++26 (when sqrt(), pow() are constexpr)

template<typename Dimensionless, typename Quantity>
auto operator/(const Quantity &x, Dimensionless y)

divide quantity x by dimensionless value y

note: doesn not require unit scaling, so constexpr with c++23

template<typename Dimensionless, typename Quantity>
auto operator/(Dimensionless x, const Quantity &y)

divide dimensionless value x by quantity y

note: doesn not require unit scaling, so constexpr with c++23

template<typename Q1, typename Q2>
auto operator+(const Q1 &x, const Q2 &y)

add quantity y to quantity x. Result will have the same units as x. Representation will be the widest of {x::repr_type, y::repr_type}.

note: won’t have constexpr result w/ fractional dimension until c++26 (when sqrt(), pow() are constexpr)

Pre:

x and y expected to have consistent dimensions

template<typename Quantity, typename Dimensionless>
auto operator+(const Quantity &x, Dimensionless y)

subtract an arithmetic value from a dimensionless quantity

template<typename Dimensionless, typename Quantity>
auto operator+(Dimensionless x, const Quantity &y)

subtract a dimensionless quantity from an arithmetic value

template<typename Q1, typename Q2>
auto operator-(const Q1 &x, const Q2 &y)

subtract quantity y from quantity x. Result will have the same units as x. Representation will be the widest of {x::repr_type, y::repr_type}

note: won’t have constexpr result w/ fractional dimension until c++26 (when sqrt(), pow() are constexpr)

Pre:

x and y expected to have consistent dimensions

template<typename Quantity, typename Dimensionless>
auto operator-(const Quantity &x, Dimensionless y)

subtract an arithmetic value from a dimensionless quantity

template<typename Dimensionless, typename Quantity>
auto operator-(Dimensionless x, const Quantity &y)

subtract a dimensionless quantity from an arithmetic value

Support methods for arithmetic operations

group Quantity-arithmetic-support

Functions

inline auto unit_qty() const

create unit quantity with same unit as this

inline auto zero_qty() const

create zero quantity with same unit as this

inline auto reciprocal() const
template<typename Dimensionless>
inline auto scale_by(Dimensionless x) const

create quantity representing this amount multiplied by dimensionless value x

Pre:

x must be an arithmetic type such as int or double

template<typename Dimensionless>
inline auto divide_by(Dimensionless x) const

create quantity representing this quantity divided by dimensionless value x

Pre:

x must be an arithmetic type such as int or double

template<typename Dimensionless>
inline auto divide_into(Dimensionless x) const

create quantity representing dimensionless value x divided by this quantity

Pre:

x must be an arithmetic type such as int or double

Comparison

Support methods for comparison operators

group Quantity-comparison-support

Functions

template<typename Quantity2>
static inline auto compare(const quantity &x, const Quantity2 &y)

compare two quantity instances, under three-way comparison