docs: "Basic Concepts" and "Interface Introduction" chapters updated

This commit is contained in:
Mateusz Pusz
2023-10-25 21:39:09 +02:00
parent 6c28d743db
commit ebc5757835
2 changed files with 42 additions and 40 deletions

View File

@@ -1,7 +1,10 @@
# Basic Concepts # Basic Concepts
The most important concepts in the **mp-units** library are `Dimension`, `QuantitySpec`, `Unit`, The most important concepts in the **mp-units** library are [`Dimension`](#Dimension),
`Reference`, `Representation`, `Quantity`, and `QuantityPoint`: [`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 ```mermaid
flowchart TD flowchart TD
@@ -29,7 +32,7 @@ flowchart TD
`Dimension` concept matches a [dimension](../../appendix/glossary.md#dimension) of either a base `Dimension` concept matches a [dimension](../../appendix/glossary.md#dimension) of either a base
or derived [quantity](../../appendix/glossary.md#quantity): or derived [quantity](../../appendix/glossary.md#quantity):
- [Base dimensions](../../appendix/glossary.md#base-dimension) are explicitly defined by a user - [Base dimensions](../../appendix/glossary.md#base-dimension) are explicitly defined by the user
by inheriting from the instantiation of a `base_dimension` class template. It should be instantiated with by inheriting from the instantiation of a `base_dimension` class template. It should be instantiated with
a unique symbol identifier describing this dimension in a specific a unique symbol identifier describing this dimension in a specific
[system of quantities](../../appendix/glossary.md#system-of-quantities). [system of quantities](../../appendix/glossary.md#system-of-quantities).
@@ -44,8 +47,8 @@ or derived [quantity](../../appendix/glossary.md#quantity):
`isq::dim_luminous_intensity` are the dimensions of base quantities in the `isq::dim_luminous_intensity` are the dimensions of base quantities in the
[ISQ](../../appendix/glossary.md#isq). [ISQ](../../appendix/glossary.md#isq).
IEC 80000 provides `iec80000::dim_traffic_intensity` base dimension to extend ISQ The implementation of IEC 80000 in this library provides `iec80000::dim_traffic_intensity`
with information technology quantities. base dimension to extend ISQ with information technology quantities.
A `Dimension` can be defined by the user in the following way: A `Dimension` can be defined by the user in the following way:
@@ -182,9 +185,9 @@ and when `T` is implicitly convertible to `V`.
`si::second`, `si::metre`, `si::kilogram`, `si::ampere`, `si::kelvin`, `si::mole`, and `si::candela` `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). are the base units of [SI](../../appendix/glossary.md#si).
`si::kilo<si::metre>` is a prefixed unit on length. `si::kilo<si::metre>` is a prefixed unit of length.
`si::radian`, `si::newton`, and `si::watt` are examples of named derived quantities within `si::radian`, `si::newton`, and `si::watt` are examples of named derived units within
[SI](../../appendix/glossary.md#si). [SI](../../appendix/glossary.md#si).
`non_si::minute` is an example of a scaled unit of time. `non_si::minute` is an example of a scaled unit of time.
@@ -226,7 +229,7 @@ and is satisfied by:
`si::second` is specified to measure `isq::time`. `si::second` is specified to measure `isq::time`.
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 be a [dimensionless quantity](../../appendix/glossary.md#dimensionless-quantity).
@@ -241,7 +244,7 @@ units can be passed as an argument to a `prefixed_unit` class template.
All units in the [SI](../../appendix/glossary.md#si) can be prefixed with SI-defined prefixes. All units in the [SI](../../appendix/glossary.md#si) can be prefixed with SI-defined prefixes.
Some [off-system units](../../appendix/glossary.md#off-system-unit) like `non_si::day` Some [off-system units](../../appendix/glossary.md#off-system-unit) like `non_si::day`
can't be prefixed. To enforce that the following has to be provided: can't be prefixed. To enforce that, the following has to be provided:
```cpp ```cpp
template<> inline constexpr bool unit_can_be_prefixed<non_si::day> = false; template<> inline constexpr bool unit_can_be_prefixed<non_si::day> = false;
@@ -259,7 +262,7 @@ concept with an associated quantity type implicitly convertible to `V`.
or the quantity type associated with `T` may not be derived from the kind of `V`. or the quantity type associated with `T` may not be derived from the kind of `V`.
This condition is required to make `dimensionless[si::radian]` invalid as `si::radian` should This condition is required to make `dimensionless[si::radian]` invalid as `si::radian` should
be only used for `isq::angular_measure` which is a be only used for `isq::angular_measure`, which is a
[nested quantity kind within the dimensionless quantities tree](dimensionless_quantities.md/#nested-quantity-kinds). [nested quantity kind within the dimensionless quantities tree](dimensionless_quantities.md/#nested-quantity-kinds).
@@ -297,10 +300,9 @@ A `Reference` can either be:
`ReferenceOf` concept is satisfied by references `T` that match the following value `V`: `ReferenceOf` concept is satisfied by references `T` that match the following value `V`:
| `V` | Condition | | `V` | Condition |
|----------------------|-----------------------------------------------------------------------------------------------| |----------------|-----------------------------------------------------------------------------------------------|
| `Dimension` | The dimension of a quantity specification satisfies [`DimensionOf<V>`](#DimensionOf) concept. | | `Dimension` | The dimension of a quantity specification satisfies [`DimensionOf<V>`](#DimensionOf) concept. |
| `QuantitySpec` | The quantity specification satisfies [`QuantitySpecOf<V>`](#QuantitySpecOf) concept. | | `QuantitySpec` | The quantity specification satisfies [`QuantitySpecOf<V>`](#QuantitySpecOf) concept. |
| `quantity_character` | The quantity specification has a character of `V`. |
## `Representation<T>` { #Representation } ## `Representation<T>` { #Representation }
@@ -324,8 +326,8 @@ with `true` for one or more of the following variable templates:
??? abstract "Examples" ??? abstract "Examples"
If we want to use scalar types to 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:
```cpp ```cpp
template<class T> template<class T>
@@ -337,14 +339,14 @@ with `true` for one or more of the following variable templates:
## `Quantity<T>` { #Quantity } ## `Quantity<T>` { #Quantity }
`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 and instantiation of a `quantity` class template. satisfied by all types being or deriving from an instantiation of a `quantity` class template.
??? abstract "Examples" ??? abstract "Examples"
All of `42 * m`, `42 * si::metre`, `42 * isq::height[m]`, and `isq::height(42 * m)` create a quantity 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. and thus satisfy a `Quantity` concept.
A quantity type can also be specified explicitly (e.g. `quantity<si::metre, int>`, A quantity type can also be specified explicitly (e.g., `quantity<si::metre, int>`,
`quantity<isq::height[m]>`). `quantity<isq::height[m]>`).
### `QuantityOf<T, V>` { #QuantityOf } ### `QuantityOf<T, V>` { #QuantityOf }
@@ -359,7 +361,7 @@ is `true`.
the library. It is satisfied by either: 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 an `relative_point_origin` class template. - All types derived from a `relative_point_origin` class template.
??? abstract "Examples" ??? abstract "Examples"
@@ -390,8 +392,8 @@ implicitly convertible from quantity specification `V`, which means that `V` mus
then it can't be used as a point origin for _points_ of `isq::length` or `isq::width` as none of them then it can't be used as a point origin for _points_ of `isq::length` or `isq::width` as none of them
is implicitly convertible to `isq::altitude`: is implicitly convertible to `isq::altitude`:
- not every "length" is an "altitude", - not every _length_ is an _altitude_,
- "width" is not compatible with "altitude". - _width_ is not compatible with _altitude_.
## `QuantityPoint<T>` { #QuantityPoint } ## `QuantityPoint<T>` { #QuantityPoint }

View File

@@ -10,10 +10,10 @@ inline constexpr struct metre : named_unit<"m", kind_of<isq::length>> {} metre;
inline constexpr struct second : named_unit<"s", kind_of<isq::time>> {} second; inline constexpr struct second : named_unit<"s", kind_of<isq::time>> {} second;
``` ```
Please note that the above reuses the same identifier for a type and its object. The rationale Please note that the above reuses the same identifier for a type and its value. The rationale
behind this is that: behind this is that:
- Users always work with objects and never have to spell such a type name. - Users always work with values and never have to spell such a type name.
- The types appear in the compilation errors and during debugging. - The types appear in the compilation errors and during debugging.
!!! important !!! important
@@ -33,17 +33,17 @@ to improve the user experience while debugging the program or analyzing the comp
!!! note !!! note
Such a practice is rare in the industry. Some popular C++ physical units libraries Such a practice is rare in the industry. Some popular C++ physical units libraries
generate enormously long error messages where even only the first line failed o fit generate enormously long error messages where even only the first line failed to fit
on a slide with a tiny font. on a slide with a tiny font.
## Entities composability ## Entities composability
Many physical units libraries (in C++ or any other programming language) assign strong types Many physical units libraries (in C++ or any other programming language) assign strong types
to library entities (e.g. derived units). While `metre_per_second` as a type may not look too to library entities (e.g., derived units). While `metre_per_second` as a type may not look too
scary, consider, for example, units of angular momentum. If we followed this path, its scary, consider, for example, units of angular momentum. If we followed this path, its
[coherent unit](../../appendix/glossary.md#coherent-derived-unit) would look like [coherent unit](../../appendix/glossary.md#coherent-derived-unit) would look like
`kilogram_metre_sq_per_second`. Now, consider how many scaled versions of this unit would you `kilogram_metre_sq_per_second`. Now, consider how many scaled versions of this unit you would
predefine in the library to ensure that all users are happy with your choice? predefine in the library to ensure that all users are happy with your choice?
How expensive would it be from the implementation point of view? How expensive would it be from the implementation point of view?
What about potential future standardization efforts? What about potential future standardization efforts?
@@ -55,7 +55,7 @@ possible. For example, to create a quantity with a unit of speed, one may write:
quantity<si::metre / si::second> q; quantity<si::metre / si::second> q;
``` ```
In case we use such an unit often and would prefer to have a handy helper for it, we can In case we use such a unit often and would prefer to have a handy helper for it, we can
always do something like this: always do something like this:
```cpp ```cpp
@@ -63,7 +63,7 @@ constexpr auto metre_per_second = si::metre / si::second;
quantity<metre_per_second> q; quantity<metre_per_second> q;
``` ```
or choose any shorter identifier of your choice. or choose any shorter identifier of our choice.
Coming back to the angular momentum case, thanks to the composability of units, a user can Coming back to the angular momentum case, thanks to the composability of units, a user can
create such a quantity in the following way: create such a quantity in the following way:
@@ -74,13 +74,13 @@ auto q = la_vector{1, 2, 3} * isq::angular_momentum[kg * m2 / s];
``` ```
It is a much better solution. It is terse and easy to understand. Please also notice how It is a much better solution. It is terse and easy to understand. Please also notice how
easy it is to obtain any scaled version of such a unit (e.g. `mg * square(mm) / min`) easy it is to obtain any scaled version of such a unit (e.g., `mg * square(mm) / min`)
without having to introduce hundreds of types to predefine them. without having to introduce hundreds of types to predefine them.
## Value-based equations ## Value-based equations
The **mp-units** library is based on C++20, which greatly improves a user's experience. One of The **mp-units** library is based on C++20, significantly improving user experience. One of
such improvements are value-based equations. such improvements are value-based equations.
As we have learned above, the entities are being used as values in the code, and they compose. As we have learned above, the entities are being used as values in the code, and they compose.
@@ -89,7 +89,7 @@ This is a huge improvement compared to what we can find in other physical units
what we have to deal with when we want to write some equations for `std::ratio`. what we have to deal with when we want to write some equations for `std::ratio`.
For example, below are a few definitions of the SI derived units showing the power of C++20 For example, below are a few definitions of the SI derived units showing the power of C++20
extensions to Non-Type Template Parameters, which allows us to directly pass a result of extensions to Non-Type Template Parameters, which allow us to directly pass a result of
the value-based [unit equation](../../appendix/glossary.md#unit-equation) to a class template the value-based [unit equation](../../appendix/glossary.md#unit-equation) to a class template
definition: definition:
@@ -141,7 +141,7 @@ The same type identifier will be visible in the compilation error (in case it ha
### Identities ### Identities
As mentioned above, equations can be done on dimensions, quantities, and units. Each such domain must As mentioned above, equations can be performed on dimensions, quantities, and units. Each such domain must
introduce an identity object that can be used in the resulting expressions. Here is the list of introduce an identity object that can be used in the resulting expressions. Here is the list of
identities used in the library: identities used in the library:
@@ -152,7 +152,7 @@ identities used in the library:
| `QuantitySpec` | `dimensionless` | | `QuantitySpec` | `dimensionless` |
| `Unit` | `one` | | `Unit` | `one` |
In the equations, a user can explicitly refer to an identity object: In the equations, a user can explicitly refer to an identity object. For example:
```cpp ```cpp
constexpr auto my_unit = one / second; constexpr auto my_unit = one / second;
@@ -172,7 +172,7 @@ constexpr auto my_unit = one / second;
### Supported operations and their results ### Supported operations and their results
There are only a few operations that one can do on such entities and the result of each of them has There are only a few operations that one can do on such entities, and the result of each of them has
its unique representation in the library: its unique representation in the library:
| Operation | Resulting template expression arguments | | Operation | Resulting template expression arguments |
@@ -208,7 +208,7 @@ the resulting expression template.
``` ```
This is probably the most important of all the steps, as it allows comparing types and enables This is probably the most important of all the steps, as it allows comparing types and enables
the rest of simplification rules. the rest of the simplification rules.
2. **Aggregation** 2. **Aggregation**
@@ -263,13 +263,13 @@ Thanks to all of the features described above, a user may write the code like th
```cpp ```cpp
using namespace mp_units::si::unit_symbols; using namespace mp_units::si::unit_symbols;
auto speed = 60. * isq::speed[km / h]; quantity speed = 60. * isq::speed[km / h];
auto duration = 8 * s; quantity duration = 8 * s;
auto acceleration = speed / duration; quantity acceleration = speed / duration;
std::cout << "acceleration: " << acceleration << " (" << acceleration.in(m / s2) << ")\n"; std::cout << "acceleration: " << acceleration << " (" << acceleration.in(m / s2) << ")\n";
``` ```
The `acceleration`, being the result of the above code, has the following type The `acceleration` quantity, being the result of the above code, has the following type
(after stripping the `mp_units` namespace for brevity): (after stripping the `mp_units` namespace for brevity):
```text ```text