docs: "Basic Concepts" chapter revised

This commit is contained in:
Mateusz Pusz
2023-08-29 14:17:14 +02:00
parent bf35ddb51b
commit 7c41561c0d
4 changed files with 190 additions and 92 deletions

View File

@@ -13,18 +13,18 @@ flowchart TD
Quantity --- QuantityPoint Quantity --- QuantityPoint
PointOrigin --- QuantityPoint PointOrigin --- QuantityPoint
click Dimension "#dimension" click Dimension "#Dimension"
click QuantitySpec "#quantityspec" click QuantitySpec "#QuantitySpec"
click Unit "#unit" click Unit "#Unit"
click Reference "#reference" click Reference "#Reference"
click Representation "#representation" click Representation "#Representation"
click Quantity "#quantity" click Quantity "#Quantity"
click PointOrigin "#pointorigin" click PointOrigin "#PointOrigin"
click QuantityPoint "#quantitypoint" click QuantityPoint "#QuantityPoint"
``` ```
## `Dimension` ## `Dimension<T>` { #Dimension }
`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):
@@ -47,17 +47,29 @@ or derived [quantity](../../appendix/glossary.md#quantity):
IEC 80000 provides `iec80000::dim_traffic_intensity` base dimension to extend ISQ IEC 80000 provides `iec80000::dim_traffic_intensity` base dimension to extend ISQ
with information technology quantities. with information technology quantities.
`derived_dimension<isq::dim_length, per<isq::dim_time>>` is a resulting dimension of
`isq::dim_length / isq::dim_time`.
A `Dimension` can be defined by the user in the following way: A `Dimension` can be defined by the user in the following way:
```cpp ```cpp
inline constexpr struct dim_length : base_dimension<"L"> {} dim_length; inline constexpr struct dim_length : base_dimension<"L"> {} dim_length;
``` ```
The division on quantity specifications also divides their dimensions:
## `QuantitySpec` ```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` concept is satisfied when both arguments satisfy a [`Dimension`](#Dimension) concept and
when they compare equal.
## `QuantitySpec<T>` { #QuantitySpec }
`QuantitySpec` concept matches all the [quantity specifications](../../appendix/glossary.md#quantity_spec) `QuantitySpec` concept matches all the [quantity specifications](../../appendix/glossary.md#quantity_spec)
including: including:
@@ -90,9 +102,6 @@ including:
`isq::area`, `isq::speed`, `isq::moment_of_force` are only a few of many derived quantities provided `isq::area`, `isq::speed`, `isq::moment_of_force` are only a few of many derived quantities provided
in the [ISQ](../../appendix/glossary.md#isq). in the [ISQ](../../appendix/glossary.md#isq).
`derived_quantity_spec<isq::length, per<isq::time>>` is a resulting quantity specification of
`isq::length / isq::time`.
`QuantitySpec` can be defined by the user in one of the following ways: `QuantitySpec` can be defined by the user in one of the following ways:
=== "C++23" === "C++23"
@@ -119,8 +128,35 @@ including:
QUANTITY_SPEC(speed, length / time); 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`
### `QuantitySpecOf<T, V>` { #QuantitySpecOf }
`QuantitySpecOf` concept is satisfied when both arguments satisfy a [`QuantitySpec`](#QuantitySpec) concept
and when `T` is implicitly convertible to `V`.
??? note "More details"
Additionally:
- `T` should not be a [nested quantity specification of `V`](dimensionless_quantities.md/#nested-quantity-kinds)
- either `T` is quantity kind or `V` should not be a
[nested quantity specification of `T`](dimensionless_quantities.md/#nested-quantity-kinds)
Those additional conditions are required to make the following work:
```cpp
static_assert(ReferenceOf<si::radian, isq::angular_measure>);
static_assert(!ReferenceOf<si::radian, dimensionless>);
static_assert(!ReferenceOf<isq::angular_measure[si::radian], dimensionless>);
static_assert(ReferenceOf<one, isq::angular_measure>);
static_assert(!ReferenceOf<dimensionless[one], isq::angular_measure>);
```
## `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:
@@ -130,7 +166,7 @@ including:
- Named scaled units defined by a user by inheriting from the `named_unit` class template instantiated - Named scaled units defined by a user by inheriting from the `named_unit` class template instantiated
with a unique symbol identifier and a product of multiplying another unit with some magnitude. with a unique symbol identifier and a product of multiplying another unit with some magnitude.
- Prefixed units defined by a user by inheriting from the `prefixed_unit` class template instantiated - Prefixed units defined by a user by inheriting from the `prefixed_unit` class template instantiated
with a magnitude and a unit to be prefixed. with a prefix symbol, a magnitude, and a unit to be prefixed.
- [Derived named units](../../appendix/glossary.md#derived-unit) defined by a user by inheriting from the - [Derived named units](../../appendix/glossary.md#derived-unit) defined by a user by inheriting from the
`named_unit` class template instantiated with a unique symbol identifier and a result of `named_unit` class template instantiated with a unique symbol identifier and a result of
[unit equation](../../appendix/glossary.md#unit-equation) passed as an argument. [unit equation](../../appendix/glossary.md#unit-equation) passed as an argument.
@@ -139,7 +175,7 @@ including:
!!! note !!! note
In the **mp-units** library, physical constants are also implemented as units. In the **mp-units** library, [physical constants are also implemented as units](faster_than_lightspeed_constants.md).
??? abstract "Examples" ??? abstract "Examples"
@@ -151,8 +187,6 @@ including:
`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 quantities within
[SI](../../appendix/glossary.md#si). [SI](../../appendix/glossary.md#si).
`derived_unit<si::metre, per<si::second>>` is a resulting derived unit of `si::metre / si::second`.
`non_si::minute` is an example of a scaled unit of time. `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. `si::si2019::speed_of_light_in_vacuum` is a physical constant standardized by the SI in 2019.
@@ -160,15 +194,23 @@ including:
`Unit` can be defined by the user in one of the following ways: `Unit` can be defined by the user in one of the following ways:
```cpp ```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 second : named_unit<"s", kind_of<isq::time>> {} second;
inline constexpr struct gram : named_unit<"g", kind_of<isq::mass>> {} gram; 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 minute : named_unit<"min", mag<60> * second> {} minute;
inline constexpr struct kilogram : decltype(kilo<gram>) {} kilogram; inline constexpr struct kilogram : decltype(kilo<gram>) {} kilogram;
inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton; 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`
### `AssociatedUnit<T>` { #AssociatedUnit }
`AssociatedUnit` concept describes a [unit with an associated quantity](../../appendix/glossary.md#associated-unit) `AssociatedUnit` concept describes a [unit with an associated quantity](../../appendix/glossary.md#associated-unit)
and is satisfied by: and is satisfied by:
@@ -180,15 +222,18 @@ and is satisfied by:
??? abstract "Examples" ??? abstract "Examples"
All units in the [SI](../../appendix/glossary.md#si) have associated quantities. All units in the [SI](../../appendix/glossary.md#si) have associated quantities. For example,
`si::second` is specified to measure `isq::time`.
Natural units typically do not have an associated quantity. 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`
would be a [dimensionless quantity](../../appendix/glossary.md#dimensionless-quantity).
### `PrefixableUnit` ### `PrefixableUnit<T>` { #PrefixableUnit }
`PrefixableUnit` concept is satisfied by all units derived from a `named_unit` class template for `PrefixableUnit` concept is satisfied by all units derived from a `named_unit` class template for
which a customization point `unit_can_be_prefixed<U>` was not explicitly set to `false`. Such which a customization point `unit_can_be_prefixed<T{}>` was not explicitly set to `false`. Such
units can be passed as an argument to a `prefixed_unit` class template. units can be passed as an argument to a `prefixed_unit` class template.
??? abstract "Examples" ??? abstract "Examples"
@@ -196,23 +241,37 @@ 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. can't be prefixed. To enforce that the following has to be provided:
### `UnitOf<QS>` { #unitof } ```cpp
template<> inline constexpr bool unit_can_be_prefixed<non_si::day> = false;
`UnitOf<QS>` concept is satisfied for all units matching an [`AssociatedUnit`](#associatedunit) ```
concept with an associated quantity type implicitly convertible to `QS`.
## `Reference` ### `UnitOf<T, V>` { #UnitOf }
`Reference` concept is satisfied by all [quantity reference types](../../appendix/glossary.md#reference) `UnitOf` concept is satisfied for all units `T` matching an [`AssociatedUnit`](#AssociatedUnit)
types. Such types provide all the meta-information required to create a [`Quantity`](#quantity). concept with an associated quantity type implicitly convertible to `V`.
A `Reference` can be either:
- An [AssociatedUnit](#associatedunit) ??? note "More details"
- 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. Additionally, the kind of `V` and the kind of quantity type associated with `T` must be the same,
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
be only used for `isq::angular_measure` which is a
[nested quantity kind within the dimensionless quantities tree](dimensionless_quantities.md/#nested-quantity-kinds).
## `Reference<T>` { #Reference }
`Reference` concept is satisfied by all [quantity reference](../../appendix/glossary.md#reference)
types. Such types provide all the meta-information required to create a [`Quantity`](#Quantity).
A `Reference` can either be:
- An [AssociatedUnit](#AssociatedUnit).
- 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.
??? abstract "Examples" ??? abstract "Examples"
@@ -223,108 +282,142 @@ A `Reference` can be either:
instantiate a quantity of `isq::height` with a unit of `si::metre`. instantiate a quantity of `isq::height` with a unit of `si::metre`.
### `ReferenceOf<V>` { #referenceof } ### `ReferenceOf<T, V>` { #ReferenceOf }
`ReferenceOf<V>` concept is satisfied by references 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 is the same as `V` | | `Dimension` | The dimension of a quantity specification satisfies [`DimensionOf<V>`](#DimensionOf) concept. |
| `QuantitySpec` | The quantity specification is implicitly convertible to `V` | | `QuantitySpec` | The quantity specification satisfies [`QuantitySpecOf<V>`](#QuantitySpecOf) concept. |
| `quantity_character` | The quantity specification has a character of `V` | | `quantity_character` | The quantity specification has a character of `V`. |
## `Representation` ## `Representation<T>` { #Representation }
`Representation` concept constraints a type of a number that stores the `Representation` concept constraints a type of a number that stores the
[value of a quantity](../../appendix/glossary.md#quantity-value). [value of a quantity](../../appendix/glossary.md#quantity-value).
### `RepresentationOf<Ch>` { #representationof } ### `RepresentationOf<T, Ch>` { #RepresentationOf }
`RepresentationOf<Ch>` concept is satisfied by all `Representation` types that are of a specified `RepresentationOf` concept is satisfied by all `Representation` types that are of a specified
[quantity character](../../appendix/glossary.md#character). A user can declare a custom representation [quantity character](../../appendix/glossary.md#character) `Ch`.
type to be of a specific character by providing the specialization with `true` for one or more of
the following variable templates: A user can declare a custom representation type to be of a specific character by providing the specialization
with `true` for one or more of the following variable templates:
- `is_scalar<T>` - `is_scalar<T>`
- `is_vector<T>` - `is_vector<T>`
- `is_tensor<T>` - `is_tensor<T>`
## `Quantity` ??? abstract "Examples"
If we want to use scalar types to 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:
```cpp
template<class T>
requires mp_units::is_scalar<T>
inline constexpr bool mp_units::is_vector<T> = true;
```
## `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 and instantiation of a `quantity` class template.
??? abstract "Examples" ??? abstract "Examples"
All of `42 * m`, `42 * si::metre`, `42 * isq::height[m]` create a quantity and thus satisfy All of `42 * m`, `42 * si::metre`, `42 * isq::height[m]`, and `isq::height(42 * m)` create a quantity
a `Quantity` concept. and thus satisfy a `Quantity` concept.
A quantity type can also be specified explicitly (i.e. `quantity<si::metre, int>`, A quantity type can also be specified explicitly (i.e. `quantity<si::metre, int>`,
`quantity<isq::height[m]>`). `quantity<isq::height[m]>`).
### `QuantityOf<V>` { #quantityof } ### `QuantityOf<T, V>` { #QuantityOf }
`QuantityOf<V>` concept is satisfied by all the quantities for which a [`ReferenceOf<V>`](#referenceof) `QuantityOf` concept is satisfied by all the quantities for which a [`ReferenceOf<V>`](#ReferenceOf)
is `true`. is `true`.
## `PointOrigin`
## `PointOrigin<T>` { #PointOrigin }
`PointOrigin` concept matches all [quantity point origins](../../appendix/glossary.md#point-origin) in `PointOrigin` concept matches all [quantity point origins](../../appendix/glossary.md#point-origin) in
the library. It is satisfied by either: the library. It is satisfied by either:
- Compile-time known [`QuantityPoint`](#quantitypoint)
- 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.
??? abstract "Examples" ??? abstract "Examples"
The types of both definitions below satisfy a `PointOrigin` concept: The types of both definitions below satisfy a `PointOrigin` concept:
```cpp ```cpp
inline constexpr struct mean_sea_level : absolute_point_origin<isq::height> {} mean_sea_level; inline constexpr struct absolute_zero : absolute_point_origin<isq::thermodynamic_temperature> {} absolute_zero;
inline constexpr auto ice_point = quantity_point<isq::thermodynamic_temperature[K]>{273.15}; inline constexpr struct ice_point : relative_point_origin<absolute_zero + 273.15 * kelvin> {} ice_point;
``` ```
### `PointOriginFor<T, V>` { #PointOriginFor }
### `PointOriginFor<QS>` { #pointoriginfor } `PointOriginFor` concept is satisfied by all [`PointOrigin`](#PointOrigin) types that have quantity type
implicitly convertible from quantity specification `V`, which means that `V` must satisfy
[`QuantitySpecOf<T::quantity_spec>`](#QuantitySpecOf).
`PointOriginFor<QS>` concept is satisfied by all [`PointOrigin`](#pointorigin) types that are defined using ??? abstract "Examples"
a provided quantity specification.
`ice_point` can serve as a point origin for _points_ of `isq::Celsius_temperature` because this quantity
type implicitly converts to `isq::thermodynamic_temperature`.
However, if we define `mean_sea_level` in the following way:
```cpp
inline constexpr struct mean_sea_level : absolute_point_origin<isq::altitude> {} mean_sea_level;
```
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`:
- not every "length" is an "altitude",
- "width" is not compatible with "altitude".
## `QuantityPoint` ## `QuantityPoint<T>` { #QuantityPoint }
`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" ??? abstract "Examples"
The following specifies a quantity point defined in terms of an ice point provided in the previous example: The following specifies a quantity point defined in terms of an `ice_point` quantity point origin
provided in the previous example:
```cpp ```cpp
constexpr auto room_reference_temperature = quantity_point<isq::Celsius_temperature[deg_C], ice_point>{21}; constexpr auto room_reference_temperature = ice_point + isq::Celsius_temperature(21 * deg_C);
``` ```
### `QuantityPointOf<V>` { #quantitypointof } ### `QuantityPointOf<T, V>` { #QuantityPointOf }
`QuantityPointOf<V>` concept is satisfied by all the quantity points for which either: `QuantityPointOf` concept is satisfied by all the quantity points `T` that match the following value `V`:
- a [`ReferenceOf<V>`](#referenceof) is `true`. | `V` | Condition |
- the type of `V` satisfies [`PointOrigin`](#pointorigin) concept and the quantity point's |---------------|----------------------------------------------------------------------------------|
[absolute point origin](../../appendix/glossary.md#absolute-point-origin) is convertible to `V`. | `Reference` | The quantity point reference satisfies [`ReferenceOf<V>`](#ReferenceOf) concept. |
| `PointOrigin` | The _point_ and `V` have the same absolute point origin. |
## `QuantityLike`
## `QuantityLike<T>` { #QuantityLike }
`QuantityLike` concept provides interoperability with other libraries and is satisfied by a type `T` `QuantityLike` concept provides interoperability with other libraries and is satisfied by a type `T`
for which an instantiation of `quantity_like_traits` type trait yields a valid type that provides: for which an instantiation of `quantity_like_traits` type trait yields a valid type that provides:
- static 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`,
- `number(T)` static member function returning a type convertible to `rep` - `value(T)` static member function returning a raw value of the quantity.
??? abstract "Examples" ??? abstract "Examples"
@@ -332,24 +425,27 @@ for which an instantiation of `quantity_like_traits` type trait yields a valid t
```cpp ```cpp
template<> template<>
struct quantity_like_traits<std::chrono::seconds> { struct mp_units::quantity_like_traits<std::chrono::seconds> {
static constexpr auto reference = si::second; static constexpr auto reference = si::second;
using rep = std::chrono::seconds::rep; using rep = std::chrono::seconds::rep;
[[nodiscard]] static constexpr rep number(const std::chrono::seconds& q) { return q.count(); } [[nodiscard]] static constexpr rep value(const std::chrono::seconds& q) { return q.count(); }
}; };
quantity q(42s);
``` ```
## `QuantityPointLike`
## `QuantityPointLike<T>` { #QuantityPointLike }
`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 member `reference` that matches the [`Reference`](#reference) concept - Static data member `reference` that matches the [`Reference`](#Reference) concept
- static 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`
- `relative(T)` static member function returning a type that can be used to construct - `quantity_from_origin(T)` static member function returning the `quantity` being the offset of the point
the [`QuantityPoint`](#quantitypoint) type from the origin
??? abstract "Examples" ??? abstract "Examples"
@@ -357,13 +453,15 @@ for which an instantiation of `quantity_point_like_traits` type trait yields a v
```cpp ```cpp
template<typename C> template<typename C>
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::seconds>> { struct mp_units::quantity_point_like_traits<std::chrono::time_point<C, std::chrono::seconds>> {
static constexpr auto reference = si::second; static constexpr auto reference = si::second;
static constexpr auto point_origin = absolute_point_origin<isq::time>; static constexpr auto point_origin = chrono_point_origin;
using rep = Rep; using rep = std::chrono::seconds::rep;
[[nodiscard]] static constexpr auto relative(const std::chrono::time_point<C, std::chrono::seconds>& qp) [[nodiscard]] static constexpr auto quantity_from_origin(const std::chrono::time_point<C, std::chrono::seconds>& qp)
{ {
return std::chrono::duration_cast<std::chrono::seconds>(qp.time_since_epoch()); return quantity{std::chrono::duration_cast<std::chrono::seconds>(qp.time_since_epoch())};
} }
}; };
quantity_point qp(time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now()));
``` ```

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`](basic_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

@@ -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`](basic_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.

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](basic_concepts.md#PrefixableUnit) can be prefixed in the following
way: way:
```cpp ```cpp