docs: "Design Overview" chapter added and "Concepts" chapter reworked

This commit is contained in:
Mateusz Pusz
2023-10-31 09:45:42 +01:00
parent ebc5757835
commit 3dba9416cb
9 changed files with 409 additions and 182 deletions

View File

@ -98,7 +98,7 @@ to form a quantity.
The same applies to the `quantity_point` construction. To prevent similar issues during The same applies to the `quantity_point` construction. To prevent similar issues during
construction, it always needs to get both a `quantity` and construction, it always needs to get both a `quantity` and
a [`PointOrigin`](../users_guide/framework_basics/basic_concepts.md#PointOrigin) that we use a [`PointOrigin`](../users_guide/framework_basics/concepts.md#PointOrigin) that we use
as a reference point. as a reference point.
@ -156,7 +156,7 @@ code.
!!! note !!! note
In case you have a good idea of how to rename In case you have a good idea of how to rename
[existing concepts](../users_guide/framework_basics/basic_concepts.md) to the `standard_case`, [existing concepts](../users_guide/framework_basics/concepts.md) to the `standard_case`,
please let us know in the associated [GitHub Issue](https://github.com/mpusz/mp-units/issues/93). please let us know in the associated [GitHub Issue](https://github.com/mpusz/mp-units/issues/93).

View File

@ -31,7 +31,7 @@ errors and debugging as easy and user-friendly as possible.
To achieve this goal, several techniques are applied: To achieve this goal, several techniques are applied:
- [usage of C++20 concepts](../users_guide/framework_basics/basic_concepts.md) that improve - [usage of C++20 concepts](../users_guide/framework_basics/concepts.md) that improve
compile-times and the readability of error messages when compared to the traditional template compile-times and the readability of error messages when compared to the traditional template
metaprogramming with [SFINAE](https://en.cppreference.com/w/cpp/language/sfinae), metaprogramming with [SFINAE](https://en.cppreference.com/w/cpp/language/sfinae),
- [usage of strong types for framework entities](../users_guide/framework_basics/interface_introduction.md#strong-types-instead-of-aliases) (instead of type aliases), - [usage of strong types for framework entities](../users_guide/framework_basics/interface_introduction.md#strong-types-instead-of-aliases) (instead of type aliases),

View File

@ -152,7 +152,7 @@ template<Reference auto R,
class quantity; class quantity;
``` ```
The second template parameter is constrained with a [`RepresentationOf`](basic_concepts.md#RepresentationOf) The second template parameter is constrained with a [`RepresentationOf`](concepts.md#RepresentationOf)
concept that checks if the provided representation type satisfies the requirements for the character concept that checks if the provided representation type satisfies the requirements for the character
associated with this quantity type. associated with this quantity type.

View File

@ -1,30 +1,6 @@
# Basic Concepts # Concepts
The most important concepts in the **mp-units** library are [`Dimension`](#Dimension), This chapter enumerates all the user-facing concepts in the **mp-units** library.
[`QuantitySpec`](#QuantitySpec), [`Unit`](#Unit), [`Reference`](#Reference),
[`Representation`](#Representation), [`Quantity`](#Quantity), and [`QuantityPoint`](#QuantityPoint).
The tree provided below presents how those and a few other concepts depend on each other:
```mermaid
flowchart TD
Dimension --- QuantitySpec
QuantitySpec --- Reference
Unit --- Reference
Reference --- Quantity
Representation --- Quantity
Quantity --- QuantityPoint
PointOrigin --- QuantityPoint
click Dimension "#Dimension"
click QuantitySpec "#QuantitySpec"
click Unit "#Unit"
click Reference "#Reference"
click Representation "#Representation"
click Quantity "#Quantity"
click PointOrigin "#PointOrigin"
click QuantityPoint "#QuantityPoint"
```
## `Dimension<T>` { #Dimension } ## `Dimension<T>` { #Dimension }
@ -40,31 +16,6 @@ or derived [quantity](../../appendix/glossary.md#quantity):
by the library's framework based on the [quantity equation](../../appendix/glossary.md#quantity-equation) by the library's framework based on the [quantity equation](../../appendix/glossary.md#quantity-equation)
provided in the [quantity specification](../../appendix/glossary.md#quantity_spec). provided in the [quantity specification](../../appendix/glossary.md#quantity_spec).
??? abstract "Examples"
`isq::dim_length`, `isq::dim_mass`, `isq::dim_time`, `isq::dim_electric_current`,
`isq::dim_thermodynamic_temperature`, `isq::dim_amount_of_substance`, and
`isq::dim_luminous_intensity` are the dimensions of base quantities in the
[ISQ](../../appendix/glossary.md#isq).
The implementation of IEC 80000 in this library provides `iec80000::dim_traffic_intensity`
base dimension to extend ISQ with information technology quantities.
A `Dimension` can be defined by the user in the following way:
```cpp
inline constexpr struct dim_length : base_dimension<"L"> {} dim_length;
```
The division on quantity specifications also divides their dimensions:
```cpp
static_assert((isq::length / isq::time).dimension == isq::dim_length / isq::dim_time);
```
The [dimension equation](../../appendix/glossary.md#dimension-equation) of `isq::dim_length / isq::dim_time`
results in the `derived_dimension<isq::dim_length, per<isq::dim_time>>` type.
### `DimensionOf<T, V>` { #DimensionOf } ### `DimensionOf<T, V>` { #DimensionOf }
@ -91,49 +42,6 @@ including:
- Intermediate [derived quantity](../../appendix/glossary.md#derived-quantity) specifications being - Intermediate [derived quantity](../../appendix/glossary.md#derived-quantity) specifications being
a result of a [quantity equations](../../appendix/glossary.md#quantity-equation) on other specifications. a result of a [quantity equations](../../appendix/glossary.md#quantity-equation) on other specifications.
??? abstract "Examples"
`isq::length`, `isq::mass`, `isq::time`, `isq::electric_current`, `isq::thermodynamic_temperature`,
`isq::amount_of_substance`, and `isq::luminous_intensity` are the specifications of base quantities
in the [ISQ](../../appendix/glossary.md#isq).
`isq::width`, `isq::height`, `isq::radius`, and `isq::position_vector` are only a few of many
quantities of a kind length specified in the [ISQ](../../appendix/glossary.md#isq).
`kind_of<isq::length>` behaves as any of the quantities of a kind length.
`isq::area`, `isq::speed`, `isq::moment_of_force` are only a few of many derived quantities provided
in the [ISQ](../../appendix/glossary.md#isq).
`QuantitySpec` can be defined by the user in one of the following ways:
=== "C++23"
```cpp
inline constexpr struct length : quantity_spec<dim_length> {} length;
inline constexpr struct height : quantity_spec<length> {} height;
inline constexpr struct speed : quantity_spec<length / time> {} speed;
```
=== "C++20"
```cpp
inline constexpr struct length : quantity_spec<length, dim_length> {} length;
inline constexpr struct height : quantity_spec<height, length> {} height;
inline constexpr struct speed : quantity_spec<speed, length / time> {} speed;
```
=== "Portable"
```cpp
QUANTITY_SPEC(length, dim_length);
QUANTITY_SPEC(height, length);
QUANTITY_SPEC(speed, length / time);
```
The [quantity equation](../../appendix/glossary.md#quantity-equation) of `isq::length / isq::time` results
in the `derived_quantity_spec<isq::length, per<isq::time>>` type.
### `QuantitySpecOf<T, V>` { #QuantitySpecOf } ### `QuantitySpecOf<T, V>` { #QuantitySpecOf }
@ -159,7 +67,7 @@ and when `T` is implicitly convertible to `V`.
``` ```
## `Unit<T> ` { #Unit } ## `Unit<T>` { #Unit }
`Unit` concept matches all the [units](../../appendix/glossary.md#unit) in the library including: `Unit` concept matches all the [units](../../appendix/glossary.md#unit) in the library including:
@ -180,38 +88,6 @@ and when `T` is implicitly convertible to `V`.
In the **mp-units** library, [physical constants are also implemented as units](faster_than_lightspeed_constants.md). In the **mp-units** library, [physical constants are also implemented as units](faster_than_lightspeed_constants.md).
??? abstract "Examples"
`si::second`, `si::metre`, `si::kilogram`, `si::ampere`, `si::kelvin`, `si::mole`, and `si::candela`
are the base units of [SI](../../appendix/glossary.md#si).
`si::kilo<si::metre>` is a prefixed unit of length.
`si::radian`, `si::newton`, and `si::watt` are examples of named derived units within
[SI](../../appendix/glossary.md#si).
`non_si::minute` is an example of a scaled unit of time.
`si::si2019::speed_of_light_in_vacuum` is a physical constant standardized by the SI in 2019.
`Unit` can be defined by the user in one of the following ways:
```cpp
template<PrefixableUnit auto U> struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U> {};
template<PrefixableUnit auto U> inline constexpr kilo_<U> kilo;
inline constexpr struct second : named_unit<"s", kind_of<isq::time>> {} second;
inline constexpr struct gram : named_unit<"g", kind_of<isq::mass>> {} gram;
inline constexpr struct minute : named_unit<"min", mag<60> * second> {} minute;
inline constexpr struct kilogram : decltype(kilo<gram>) {} kilogram;
inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
inline constexpr struct speed_of_light_in_vacuum : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
```
The [unit equation](../../appendix/glossary.md#unit-equation) of `si::metre / si::second` results
in the `derived_unit<si::metre, per<si::second>>` type.
### `AssociatedUnit<T>` { #AssociatedUnit } ### `AssociatedUnit<T>` { #AssociatedUnit }
@ -219,8 +95,8 @@ and when `T` is implicitly convertible to `V`.
and is satisfied by: and is satisfied by:
- All units derived from a `named_unit` class template instantiated with a unique symbol identifier - All units derived from a `named_unit` class template instantiated with a unique symbol identifier
and a [`QuantitySpec`](#quantityspec). and a [`QuantitySpec`](#quantityspec) of a [quantity kind](../../appendix/glossary.md#kind).
- All units being a result of a [unit equations](../../appendix/glossary.md#unit-equation) on other - All units being a result of [unit equations](../../appendix/glossary.md#unit-equation) on other
associated units. associated units.
??? abstract "Examples" ??? abstract "Examples"
@ -230,7 +106,7 @@ and is satisfied by:
Natural units typically do not have an associated quantity. For example, if we assume `c = 1`, Natural units typically do not have an associated quantity. For example, if we assume `c = 1`,
a `natural::second` unit can be used to measure both `time` and `length`. In such case, `speed` a `natural::second` unit can be used to measure both `time` and `length`. In such case, `speed`
would be a [dimensionless quantity](../../appendix/glossary.md#dimensionless-quantity). would have a unit of `one`.
### `PrefixableUnit<T>` { #PrefixableUnit } ### `PrefixableUnit<T>` { #PrefixableUnit }
@ -286,14 +162,6 @@ A `Reference` can either be:
- The instantiation of a `reference` class template with a [`QuantitySpec`](#QuantitySpec) passed as - The instantiation of a `reference` class template with a [`QuantitySpec`](#QuantitySpec) passed as
the first template argument and a [`Unit`](#Unit) passed as the second one. the first template argument and a [`Unit`](#Unit) passed as the second one.
??? abstract "Examples"
`si::metre` is defined in the [SI](../../appendix/glossary.md#si) as a unit of `isq::length`
and thus can be used as a reference to instantiate a quantity of length.
The expression `isq::height[m]` results with `reference<isq::height, si::metre>` which can be used to
instantiate a quantity of `isq::height` with a unit of `si::metre`.
### `ReferenceOf<T, V>` { #ReferenceOf } ### `ReferenceOf<T, V>` { #ReferenceOf }
@ -324,7 +192,7 @@ with `true` for one or more of the following variable templates:
- `is_tensor<T>` - `is_tensor<T>`
??? abstract "Examples" ??? tip
If we want to use scalar types to also express [vector quantities](character_of_a_quantity.md#defining-vector-and-tensor-quantities) If we want to use scalar types to also express [vector quantities](character_of_a_quantity.md#defining-vector-and-tensor-quantities)
(e.g., ignoring the "direction" of the vector) the following definition can be provided to enable such a behavior: (e.g., ignoring the "direction" of the vector) the following definition can be provided to enable such a behavior:
@ -341,13 +209,6 @@ with `true` for one or more of the following variable templates:
`Quantity` concept matches every [quantity](../../appendix/glossary.md#quantity) in the library and is `Quantity` concept matches every [quantity](../../appendix/glossary.md#quantity) in the library and is
satisfied by all types being or deriving from an instantiation of a `quantity` class template. satisfied by all types being or deriving from an instantiation of a `quantity` class template.
??? abstract "Examples"
All of `42 * m`, `42 * si::metre`, `42 * isq::height[m]`, and `isq::height(42 * m)` create a quantity
and thus satisfy a `Quantity` concept.
A quantity type can also be specified explicitly (e.g., `quantity<si::metre, int>`,
`quantity<isq::height[m]>`).
### `QuantityOf<T, V>` { #QuantityOf } ### `QuantityOf<T, V>` { #QuantityOf }
@ -363,14 +224,6 @@ the library. It is satisfied by either:
- All types derived from an `absolute_point_origin` class template. - All types derived from an `absolute_point_origin` class template.
- All types derived from a `relative_point_origin` class template. - All types derived from a `relative_point_origin` class template.
??? abstract "Examples"
The types of both definitions below satisfy a `PointOrigin` concept:
```cpp
inline constexpr struct absolute_zero : absolute_point_origin<isq::thermodynamic_temperature> {} absolute_zero;
inline constexpr struct ice_point : relative_point_origin<absolute_zero + 273.15 * kelvin> {} ice_point;
```
### `PointOriginFor<T, V>` { #PointOriginFor } ### `PointOriginFor<T, V>` { #PointOriginFor }
@ -380,8 +233,8 @@ implicitly convertible from quantity specification `V`, which means that `V` mus
??? abstract "Examples" ??? abstract "Examples"
`ice_point` can serve as a point origin for _points_ of `isq::Celsius_temperature` because this quantity `si::ice_point` can serve as a point origin for _points_ of `isq::Celsius_temperature` because this
type implicitly converts to `isq::thermodynamic_temperature`. quantity type implicitly converts to `isq::thermodynamic_temperature`.
However, if we define `mean_sea_level` in the following way: However, if we define `mean_sea_level` in the following way:
@ -401,15 +254,6 @@ implicitly convertible from quantity specification `V`, which means that `V` mus
`QuantityPoint` concept is satisfied by all types being either a specialization or derived from `quantity_point` `QuantityPoint` concept is satisfied by all types being either a specialization or derived from `quantity_point`
class template. class template.
??? abstract "Examples"
The following specifies a quantity point defined in terms of an `ice_point` quantity point origin
provided in the previous example:
```cpp
constexpr auto room_reference_temperature = ice_point + isq::Celsius_temperature(21 * deg_C);
```
### `QuantityPointOf<T, V>` { #QuantityPointOf } ### `QuantityPointOf<T, V>` { #QuantityPointOf }
@ -428,10 +272,10 @@ for which an instantiation of `quantity_like_traits` type trait yields a valid t
- Static data member `reference` that matches the [`Reference`](#Reference) concept, - Static data member `reference` that matches the [`Reference`](#Reference) concept,
- `rep` type that matches [`RepresentationOf`](#RepresentationOf) concept with the character provided - `rep` type that matches [`RepresentationOf`](#RepresentationOf) concept with the character provided
in `reference`, in `reference`.
- `to_numerical_value(T)` static member function returning a raw value of the quantity packed in - `to_numerical_value(T)` static member function returning a raw value of the quantity packed in
either `convert_explicitly` or `convert_implicitly` wrapper that enables implicit conversion in either `convert_explicitly` or `convert_implicitly` wrapper that enables implicit conversion in
the latter case, the latter case.
- `from_numerical_value(rep)` static member function returning `T` packed in either `convert_explicitly` - `from_numerical_value(rep)` static member function returning `T` packed in either `convert_explicitly`
or `convert_implicitly` wrapper that enables implicit conversion in the latter case. or `convert_implicitly` wrapper that enables implicit conversion in the latter case.
@ -467,13 +311,13 @@ for which an instantiation of `quantity_like_traits` type trait yields a valid t
`QuantityPointLike` concept provides interoperability with other libraries and is satisfied by a type `T` `QuantityPointLike` concept provides interoperability with other libraries and is satisfied by a type `T`
for which an instantiation of `quantity_point_like_traits` type trait yields a valid type that provides: for which an instantiation of `quantity_point_like_traits` type trait yields a valid type that provides:
- Static data member `reference` that matches the [`Reference`](#Reference) concept - Static data member `reference` that matches the [`Reference`](#Reference) concept.
- Static data member `point_origin` that matches the [`PointOrigin`](#PointOrigin) concept - Static data member `point_origin` that matches the [`PointOrigin`](#PointOrigin) concept.
- `rep` type that matches [`RepresentationOf`](#RepresentationOf) concept with the character provided - `rep` type that matches [`RepresentationOf`](#RepresentationOf) concept with the character provided
in `reference` in `reference`.
- `to_quantity(T)` static member function returning the `quantity` being the offset of the point - `to_quantity(T)` static member function returning the `quantity` being the offset of the point
from the origin packed in either `convert_explicitly` or `convert_implicitly` wrapper that enables from the origin packed in either `convert_explicitly` or `convert_implicitly` wrapper that enables
implicit conversion in the latter case, implicit conversion in the latter case.
- `from_quantity(quantity<reference, rep>)` static member function returning `T` packed in either - `from_quantity(quantity<reference, rep>)` static member function returning `T` packed in either
`convert_explicitly` or `convert_implicitly` wrapper that enables implicit conversion in the latter `convert_explicitly` or `convert_implicitly` wrapper that enables implicit conversion in the latter
case. case.

View File

@ -0,0 +1,382 @@
# Design Overview
The most important entities in the **mp-units** library are:
- [quantity](#quantity),
- [quantity point](#quantity-point),
- [unit](#unit),
- [dimension](#dimension),
- [quantity specification](#quantity-specification)
- [quantity reference](#quantity-reference),
- [quantity representation](#quantity-representation).
The graph provided below presents how those and a few other entities depend on each other:
```mermaid
flowchart TD
Unit --- Reference
Dimension --- QuantitySpec["Quantity specification"]
quantity_character["Quantity character"] --- QuantitySpec
QuantitySpec --- Reference["Quantity reference"]
Reference --- Quantity
quantity_character --- Representation
Representation --- Quantity
Quantity --- QuantityPoint["Quantity point"]
PointOrigin["Point origin"] --- QuantityPoint
click Dimension "#dimension"
click quantity_character "#quantity-character"
click QuantitySpec "#quantity-specification"
click Unit "#unit"
click Reference "#quantity-reference"
click Representation "#quantity-representation"
click Quantity "#quantity"
click PointOrigin "#point-origin"
click QuantityPoint "#quantity-point"
```
## Dimension
[Dimension](../../appendix/glossary.md#dimension) specifies the dependence of a quantity on the base
quantities of a particular system of quantities. It is represented as a product of powers of factors
corresponding to the base quantities, omitting any numerical factor.
In the **mp-units** library, we use the terms:
- **base dimension** to refer to the dimension of a [base quantity](../../appendix/glossary.md#base-quantity),
- **derived dimension** to refer to the dimension of a [derived quantity](../../appendix/glossary.md#derived-quantity).
For example:
- _length_ ($\mathsf{L}$), _mass_ ($\mathsf{M}$), _time_ ($\mathsf{T}$), _electric current_ ($\mathsf{I}$),
_thermodynamic temperature_ ($\mathsf{Θ}$), _amount of substance_ ($\mathsf{N}$), and
_luminous intensity_ ($\mathsf{J}$) are the base dimensions of the [ISQ](../../appendix/glossary.md#isq).
- A derived dimension of _force_ in the [ISQ](../../appendix/glossary.md#isq) is denoted by
$\textsf{dim }F = \mathsf{LMT}^{2}$.
- The implementation of IEC 80000 in this library provides `iec80000::dim_traffic_intensity`
base dimension to extend ISQ with strong information technology quantities.
[Base dimensions](../../appendix/glossary.md#base-dimension) can be defined by the user in
the following way:
```cpp
inline constexpr struct dim_length : base_dimension<"L"> {} dim_length;
inline constexpr struct dim_time : base_dimension<"T"> {} dim_time;
```
[Derived dimensions](../../appendix/glossary.md#derived-dimension) are implicitly created
by the library's framework based on the [quantity equation](../../appendix/glossary.md#quantity-equation)
provided in the [quantity specification](../../appendix/glossary.md#quantity_spec):
=== "C++23"
```cpp
inline constexpr struct length : quantity_spec<dim_length> {} length;
inline constexpr struct time : quantity_spec<dim_time> {} time;
inline constexpr struct speed : quantity_spec<length / time> {} speed;
static_assert(speed.dimension == dim_length / dim_time);
```
=== "C++20"
```cpp
inline constexpr struct length : quantity_spec<length, dim_length> {} length;
inline constexpr struct time : quantity_spec<time, dim_time> {} time;
inline constexpr struct speed : quantity_spec<speed, length / time> {} speed;
static_assert(speed.dimension == dim_length / dim_time);
```
=== "Portable"
```cpp
QUANTITY_SPEC(length, dim_length);
QUANTITY_SPEC(time, dim_time);
QUANTITY_SPEC(speed, length / time);
static_assert(speed.dimension == dim_length / dim_time);
```
!!! important
Users should not explicitly define any derived dimensions. Those should always be implicitly
created by the framework.
The multiplication/division on quantity specifications also multiplies/divides their dimensions:
```cpp
static_assert((length / time).dimension == dim_length / dim_time);
```
The [dimension equation](../../appendix/glossary.md#dimension-equation) of `isq::dim_length / isq::dim_time`
results in the `derived_dimension<isq::dim_length, per<isq::dim_time>>` type.
## Quantity character
[ISO 80000](../appendix/references.md#ISO80000) explicitly states that quantities (even of the same kind) may have
different [characters](../../appendix/glossary.md#character):
- scalar,
- vector,
- tensor.
The quantity character in the **mp-units** library is implemented with the `quantity_character` enumeration:
```cpp
enum class quantity_character { scalar, vector, tensor };
```
!!! info
You can read more on quantity characters in the ["Character of a Quantity"](character_of_a_quantity.md)
chapter.
## Quantity specification
[Dimension is not enough to describe a quantity](systems_of_quantities.md#dimension-is-not-enough-to-describe-a-quantity).
This is why the [ISO 80000](../appendix/references.md#ISO80000) provides hundreds of named quantity
types. It turns out that there are many more quantity types in the [ISQ](../../appendix/glossary.md#isq)
than the named units in the [SI](../../appendix/glossary.md#si).
This is why the **mp-units** library introduces a quantity specification entity that stores:
- [dimension](../../appendix/glossary.md#dimension),
- quantity type/name,
- [quantity character](../../appendix/glossary.md#character),
- the [quantity equation](../../appendix/glossary.md#quantity-equation) being the recipe to create this quantity
(only for derived quantities that specify such a recipe).
!!! note
We know that it might be sometimes confusing to talk about quantities, quantity types/names, and quantity
specifications. However, it might be important to notice here that even the
[ISO 80000](../appendix/references.md#ISO80000) admits that:
> It is customary to use the same term, "quantity", to refer to both general quantities, such as length,
> mass, etc., and their instances, such as given lengths, given masses, etc. Accordingly, we are used to
> saying both that length is a quantity and that a given length is a quantity by maintaining the specification
> "general quantity, $Q$" or "individual quantity, $Q_\textsf{a}$" implicit and exploiting the linguistic
> context to remove the ambiguity.
In the **mp-units** library, we have a:
- **quantity** - implemented as a `quantity` class template,
- **quantity specification** - implemented with a `quantity_spec` class template that among others identifies
a specific **quantity type/name**.
For example:
- `isq::length`, `isq::mass`, `isq::time`, `isq::electric_current`, `isq::thermodynamic_temperature`,
`isq::amount_of_substance`, and `isq::luminous_intensity` are the specifications of base quantities
in the [ISQ](../../appendix/glossary.md#isq).
- `isq::width`, `isq::height`, `isq::radius`, and `isq::position_vector` are only a few of many
quantities of a kind length specified in the [ISQ](../../appendix/glossary.md#isq).
- `isq::area`, `isq::speed`, `isq::moment_of_force` are only a few of many derived quantities provided
in the [ISQ](../../appendix/glossary.md#isq).
Quantity specification can be defined by the user in one of the following ways:
=== "C++23"
```cpp
inline constexpr struct length : quantity_spec<dim_length> {} length;
inline constexpr struct height : quantity_spec<length> {} height;
inline constexpr struct speed : quantity_spec<length / time> {} speed;
```
=== "C++20"
```cpp
inline constexpr struct length : quantity_spec<length, dim_length> {} length;
inline constexpr struct height : quantity_spec<height, length> {} height;
inline constexpr struct speed : quantity_spec<speed, length / time> {} speed;
```
=== "Portable"
```cpp
QUANTITY_SPEC(length, dim_length);
QUANTITY_SPEC(height, length);
QUANTITY_SPEC(speed, length / time);
```
The [quantity equation](../../appendix/glossary.md#quantity-equation) of `isq::length / isq::time` results
in the `derived_quantity_spec<isq::length, per<isq::time>>` type.
## Unit
A [unit](../../appendix/glossary.md#unit) is a concrete amount of a quantity that allows us to
measure the values of [quantities of the same kind](systems_of_quantities.md#quantities-of-the-same-kind)
and represent the result as a number being the ratio of the two quantities.
For example:
- `si::second`, `si::metre`, `si::kilogram`, `si::ampere`, `si::kelvin`, `si::mole`, and `si::candela`
are the base units of the [SI](../../appendix/glossary.md#si).
- `si::kilo<si::metre>` is a prefixed unit of length.
- `si::radian`, `si::newton`, and `si::watt` are examples of named derived units within the
[SI](../../appendix/glossary.md#si).
- `non_si::minute` is an example of a scaled unit of time.
- `si::si2019::speed_of_light_in_vacuum` is a physical constant standardized by the SI in 2019.
!!! note
In the **mp-units** library, [physical constants are also implemented as units](faster_than_lightspeed_constants.md).
A unit can be defined by the user in one of the following ways:
```cpp
template<PrefixableUnit auto U> struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U> {};
template<PrefixableUnit auto U> inline constexpr kilo_<U> kilo;
inline constexpr struct second : named_unit<"s", kind_of<isq::time>> {} second;
inline constexpr struct minute : named_unit<"min", mag<60> * second> {} minute;
inline constexpr struct gram : named_unit<"g", kind_of<isq::mass>> {} gram;
inline constexpr struct kilogram : decltype(kilo<gram>) {} kilogram;
inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
inline constexpr struct speed_of_light_in_vacuum : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
```
The [unit equation](../../appendix/glossary.md#unit-equation) of `si::metre / si::second` results
in the `derived_unit<si::metre, per<si::second>>` type.
## Quantity reference
ISO defines a quantity as:
!!! quote
property of a phenomenon, body, or substance, where the property has a magnitude
that can be expressed as a number and a **_reference_**
After that, it says:
!!! quote
A reference can be a **_measurement unit_**, a measurement procedure, a reference material,
or a combination of such.
In the **mp-units** library, a quantity reference provides all the domain-specific metadata for the quantity
besides its [numerical value](../../appendix/glossary.md#numerical-value):
- all the data stored in the [quantity specification](#quantity-specification),
- [unit](#unit).
Together with the value of a [representation type](#quantity-representation), it forms a quantity.
In the library, we have two different ways to provide a reference:
- every unit with the associated [quantity kind](systems_of_quantities.md#quantities-of-the-same-kind)
is a valid reference,
- providing a unit to an indexing operator of a quantity specification explicitly instantiates
a `reference` class template with this quantity spec and a unit passed as arguments.
!!! note
All the units of the [SI](../../appendix/glossary.md#si) have associated quantity kinds
and may serve as a reference.
For example:
- `si::metre` is defined in the [SI](../../appendix/glossary.md#si) as a unit of `isq::length`
and thus can be used as a reference to instantiate a quantity of length (e.g., `42 * m`).
- The expression `isq::height[m]` results with `reference<isq::height, si::metre>`, which can be used to
instantiate a quantity of `isq::height` with a unit of `si::metre` (e.g., `42 * isq::height[m]`).
## Quantity representation
Quantity representation defines the type used to store the
[numerical value of a quantity](../../appendix/glossary.md#quantity-value). Such a type should be of
a specific [quantity character](#quantity-character) provided in the
[quantity specification](#quantity-specification).
!!! note
By default, all floating-point and integral (besides `bool`) types are treated as scalars.
## Quantity
ISO defines a quantity as:
!!! quote
property of a phenomenon, body, or substance, where the property has a magnitude
that can be expressed as a **_number_** and a **_reference_**
This is why a `quantity` class template is defined in the library as:
```cpp
template<Reference auto R,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
class quantity;
```
Its value can be easily created by multiplying/dividing the [numerical value](#quantity-representation)
and a [reference](#quantity-reference).
For example:
- All of `42 * m`, `42 * si::metre`, `42 * isq::height[m]`, and `isq::height(42 * m)` create a quantity.
- A quantity type can also be specified explicitly (e.g., `quantity<si::metre, int>`,
`quantity<isq::height[m]>`).
## Point origin
In [the affine space theory](the_affine_space.md), the point origin specifies where the "zero" of our
measurement's scale is.
In the **mp-units** library, we have two types of point origins:
- [absolute](the_affine_space.md#absolute-point-origin) - defines an absolute "zero" for our point,
- [relative](the_affine_space.md#relative-point-origin) - defines an origin that has some "offset" relative
to an absolute point.
For example:
- the absolute point origin can be defined in the following way:
```cpp
inline constexpr struct absolute_zero : absolute_point_origin<isq::thermodynamic_temperature> {} absolute_zero;
```
- the relative point origin can be defined in the following way:
```cpp
inline constexpr struct ice_point : relative_point_origin<absolute_zero + 273.15 * kelvin> {} ice_point;
```
## Quantity point
Quantity point implements a _point_ in [the affine space theory](the_affine_space.md).
In the **mp-units** library, the quantity point is implemented as:
```cpp
template<Reference auto R,
PointOriginFor<get_quantity_spec(R)> auto PO,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
class quantity_point;
```
Its value can be easily created by adding/subtracting the [quantity](#quantity) with
a [point origin](#point-origin).
For example:
- The following specifies a quantity point defined in terms of an `ice_point` provided in
the previous example:
```cpp
constexpr auto room_reference_temperature = ice_point + isq::Celsius_temperature(21 * deg_C);
```

View File

@ -107,7 +107,7 @@ accepts everything:
## Constraining function template arguments with concepts ## Constraining function template arguments with concepts
Much better generic code can be implemented using [basic concepts](basic_concepts.md) Much better generic code can be implemented using [basic concepts](concepts.md)
provided with the library: provided with the library:
```cpp ```cpp
@ -119,7 +119,7 @@ auto avg_speed(QuantityOf<isq::length> auto distance,
``` ```
This explicitly states that the arguments passed by the user must not only satisfy This explicitly states that the arguments passed by the user must not only satisfy
a [`Quantity`](basic_concepts.md#Quantity) concept but also their quantity specification must a [`Quantity`](concepts.md#Quantity) concept but also their quantity specification must
be implicitly convertible to `isq::length` and `isq::time` accordingly. This no longer leaves be implicitly convertible to `isq::length` and `isq::time` accordingly. This no longer leaves
room for error while still allowing the compiler to generate the most efficient code. room for error while still allowing the compiler to generate the most efficient code.
@ -192,4 +192,4 @@ what we expected here.
The `QuantityOf` and `QuantityPointOf` concepts are probably the most useful, but there The `QuantityOf` and `QuantityPointOf` concepts are probably the most useful, but there
are a few more to play with. A list of all the concepts can be found in are a few more to play with. A list of all the concepts can be found in
[the "Basic Concepts" chapter](basic_concepts.md). [the "Basic Concepts" chapter](concepts.md).

View File

@ -138,7 +138,7 @@ template<PrefixableUnit auto U> struct quecto_ : prefixed_unit<"q", mag_power<10
template<PrefixableUnit auto U> inline constexpr quecto_<U> quecto; template<PrefixableUnit auto U> inline constexpr quecto_<U> quecto;
``` ```
and then a [PrefixableUnit](basic_concepts.md#PrefixableUnit) can be prefixed in the following and then a [PrefixableUnit](concepts.md#PrefixableUnit) can be prefixed in the following
way: way:
```cpp ```cpp

View File

@ -55,7 +55,7 @@ the affine space.
In the **mp-units** library the _point_ abstraction is modelled by: In the **mp-units** library the _point_ abstraction is modelled by:
- [`PointOrigin` concept](basic_concepts.md#PointOrigin) that specifies measurement origin, - [`PointOrigin` concept](concepts.md#PointOrigin) that specifies measurement origin,
- `quantity_point` class template that specifies a _point_ relative to a specific predefined origin. - `quantity_point` class template that specifies a _point_ relative to a specific predefined origin.
### Absolute _point_ origin ### Absolute _point_ origin
@ -79,7 +79,7 @@ class quantity_point;
``` ```
As we can see above, the `quantity_point` class template exposes one additional parameter compared As we can see above, the `quantity_point` class template exposes one additional parameter compared
to `quantity`. The `PO` parameter satisfies a [`PointOriginFor` concept](basic_concepts.md#PointOriginFor) to `quantity`. The `PO` parameter satisfies a [`PointOriginFor` concept](concepts.md#PointOriginFor)
and specifies the origin of our measurement scale. and specifies the origin of our measurement scale.
!!! tip !!! tip

View File

@ -111,8 +111,8 @@ nav:
- User's Guide: - User's Guide:
- Terms and Definitions: users_guide/terms_and_definitions.md - Terms and Definitions: users_guide/terms_and_definitions.md
- Framework Basics: - Framework Basics:
- Basic Concepts: users_guide/framework_basics/basic_concepts.md
- Interface Introduction: users_guide/framework_basics/interface_introduction.md - Interface Introduction: users_guide/framework_basics/interface_introduction.md
- Design Overview: users_guide/framework_basics/design_overview.md
- Systems of Quantities: users_guide/framework_basics/systems_of_quantities.md - Systems of Quantities: users_guide/framework_basics/systems_of_quantities.md
- Systems of Units: users_guide/framework_basics/systems_of_units.md - Systems of Units: users_guide/framework_basics/systems_of_units.md
- Simple and Typed Quantities: users_guide/framework_basics/simple_and_typed_quantities.md - Simple and Typed Quantities: users_guide/framework_basics/simple_and_typed_quantities.md
@ -124,6 +124,7 @@ nav:
- Faster-than-lightspeed Constants: users_guide/framework_basics/faster_than_lightspeed_constants.md - Faster-than-lightspeed Constants: users_guide/framework_basics/faster_than_lightspeed_constants.md
- The Affine Space: users_guide/framework_basics/the_affine_space.md - The Affine Space: users_guide/framework_basics/the_affine_space.md
- Obtaining Metadata: users_guide/framework_basics/obtaining_metadata.md - Obtaining Metadata: users_guide/framework_basics/obtaining_metadata.md
- Concepts: users_guide/framework_basics/concepts.md
- Text Output: users_guide/framework_basics/text_output.md - Text Output: users_guide/framework_basics/text_output.md
- Defining Systems: - Defining Systems:
- Introduction: users_guide/defining_systems/introduction.md - Introduction: users_guide/defining_systems/introduction.md