mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 02:17:16 +02:00
Merge branch 'master' into feature/more-value-casts
This commit is contained in:
@ -172,7 +172,7 @@ Additionally, some CMake options were renamed to better express the impact on ou
|
||||
Before this release, the library always depended on [gsl-lite](https://github.com/gsl-lite/gsl-lite)
|
||||
to perform runtime contract and asserts checking. In this release we introduced new options
|
||||
to control if contract checking should be based on [gsl-lite](https://github.com/gsl-lite/gsl-lite),
|
||||
[ms-gsl](https://github.com/microsoft/GSL), or maybe completely disabled.
|
||||
[ms-gsl](https://github.com/microsoft/GSL), or may be completely disabled.
|
||||
|
||||
|
||||
## Freestanding support
|
||||
@ -205,7 +205,7 @@ origins. For example:
|
||||
=== "Before"
|
||||
|
||||
```cpp
|
||||
constexpr struct zero : absolute_point_origin<zero, currency> {} zero;
|
||||
constexpr struct zero final : absolute_point_origin<currency> {} zero;
|
||||
|
||||
quantity_point price_usd = zero + 100 * USD;
|
||||
```
|
||||
@ -260,6 +260,16 @@ named with its corresponding unit and with the `si::zeroth_degree_Celsius`
|
||||
|
||||
## Changes to units definitions
|
||||
|
||||
There were several known issues when units were deriving from each other
|
||||
(e.g., [#512](https://github.com/mpusz/mp-units/issues/512) and
|
||||
[#537](https://github.com/mpusz/mp-units/issues/537)). We could either highly complicate the
|
||||
framework to allow these which could result in much longer compilation times or disallow inheriting
|
||||
from units at all. We chose the second option.
|
||||
|
||||
With this release all of of the units must be marked as `final`. To enforce this we have changed
|
||||
the definition of the `Unit<T>` concept, which now requires type `T` to be `final`
|
||||
(:boom: **breaking change** :boom:).
|
||||
|
||||
[WG21 Study Group 16 (Unicode) raised concerns](https://github.com/sg16-unicode/sg16-meetings#january-24th-2024)
|
||||
about potential ABI issues when different translation units are compiled with different ordinary
|
||||
literal encodings. Those issues were resolved with a change to units definitions
|
||||
@ -272,7 +282,7 @@ is why it was renamed to `symbol_text` (:boom: **breaking change** :boom:).
|
||||
=== "Now"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct ohm : named_unit<symbol_text{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
||||
inline constexpr struct ohm final : named_unit<symbol_text{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
||||
```
|
||||
|
||||
=== "Before"
|
||||
@ -286,9 +296,48 @@ is why it was renamed to `symbol_text` (:boom: **breaking change** :boom:).
|
||||
On C++20-compliant compilers it should be enough to type the following in the unit's definition:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct ohm : named_unit<{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
||||
inline constexpr struct ohm final : named_unit<{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
||||
```
|
||||
|
||||
|
||||
## Changes to dimension, quantity specification, and point origins definitions
|
||||
|
||||
Similarly to units, now also all dimensions, quantity specifications, and point origins have to be
|
||||
marked `final` (:boom: **breaking change** :boom:).
|
||||
|
||||
=== "Now"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length;
|
||||
inline constexpr struct length final : quantity_spec<dim_length> {} length;
|
||||
|
||||
inline constexpr struct absolute_zero final : absolute_point_origin<isq::thermodynamic_temperature> {} absolute_zero;
|
||||
inline constexpr auto zeroth_kelvin = absolute_zero;
|
||||
inline constexpr struct kelvin final : named_unit<"K", kind_of<isq::thermodynamic_temperature>, zeroth_kelvin> {} kelvin;
|
||||
|
||||
inline constexpr struct ice_point final : relative_point_origin<quantity_point{273'150 * milli<kelvin>}> {} ice_point;
|
||||
inline constexpr auto zeroth_degree_Celsius = ice_point;
|
||||
inline constexpr struct degree_Celsius final : named_unit<symbol_text{u8"°C", "`C"}, kelvin, zeroth_degree_Celsius> {} degree_Celsius;
|
||||
```
|
||||
|
||||
=== "Before"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct dim_length : base_dimension<"L"> {} dim_length;
|
||||
inline constexpr struct length : quantity_spec<dim_length> {} length;
|
||||
|
||||
inline constexpr struct absolute_zero : absolute_point_origin<absolute_zero, isq::thermodynamic_temperature> {} absolute_zero;
|
||||
inline constexpr struct zeroth_kelvin : decltype(absolute_zero) {} zeroth_kelvin;
|
||||
inline constexpr struct kelvin : named_unit<"K", kind_of<isq::thermodynamic_temperature>, zeroth_kelvin> {} kelvin;
|
||||
|
||||
inline constexpr struct ice_point : relative_point_origin<quantity_point{273'150 * milli<kelvin>}> {} ice_point;
|
||||
inline constexpr struct zeroth_degree_Celsius : decltype(ice_point) {} zeroth_degree_Celsius;
|
||||
inline constexpr struct degree_Celsius : named_unit<symbol_text{u8"°C", "`C"}, kelvin, zeroth_degree_Celsius> {} degree_Celsius;
|
||||
```
|
||||
|
||||
Please also note, that the `absolute_point_origin` does not use CRTP idiom anymore (:boom: **breaking change** :boom:).
|
||||
|
||||
|
||||
## Improved text output
|
||||
|
||||
With this release, we can print not only whole quantities but also just their units or dimensions.
|
||||
@ -461,8 +510,8 @@ conversion factor. Here is a comparison of the code with previous and current de
|
||||
=== "Now"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct yard : named_unit<"yd", mag_ratio<9'144, 10'000> * si::metre> {} yard;
|
||||
inline constexpr struct foot : named_unit<"ft", mag_ratio<1, 3> * yard> {} foot;
|
||||
inline constexpr struct yard final : named_unit<"yd", mag_ratio<9'144, 10'000> * si::metre> {} yard;
|
||||
inline constexpr struct foot final : named_unit<"ft", mag_ratio<1, 3> * yard> {} foot;
|
||||
```
|
||||
|
||||
=== "Before"
|
||||
|
@ -342,7 +342,7 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
|
||||
|
||||
[`MP_UNITS_API_STD_FORMAT`](#MP_UNITS_API_STD_FORMAT){ #MP_UNITS_API_STD_FORMAT }
|
||||
|
||||
: [:octicons-tag-24: 2.2.0][use fmtlib support] · :octicons-milestone-24: `AUTO`/`ON`/`OFF` (Default: `AUTO`)
|
||||
: [:octicons-tag-24: 2.2.0][use fmtlib support] · :octicons-milestone-24: `AUTO`/`TRUE`/`FALSE` (Default: `AUTO`)
|
||||
|
||||
Enables the usage of [`std::format`](https://en.cppreference.com/w/cpp/utility/format/format)
|
||||
and associated facilities for text formatting. If it is not supported, then
|
||||
@ -352,7 +352,7 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
|
||||
|
||||
[`MP_UNITS_API_STRING_VIEW_RET`](#MP_UNITS_API_STRING_VIEW_RET){ #MP_UNITS_API_STRING_VIEW_RET }
|
||||
|
||||
: [:octicons-tag-24: 2.2.0][cmake returning string_view] · :octicons-milestone-24: `AUTO`/`ON`/`OFF` (Default: `AUTO`)
|
||||
: [:octicons-tag-24: 2.2.0][cmake returning string_view] · :octicons-milestone-24: `AUTO`/`TRUE`/`FALSE` (Default: `AUTO`)
|
||||
|
||||
Enables returning `std::string_view` from the
|
||||
[`unit_symbol()`](../users_guide/framework_basics/text_output.md#unit_symbol)
|
||||
@ -364,7 +364,7 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"}
|
||||
|
||||
[`MP_UNITS_API_NO_CRTP`](#MP_UNITS_API_NO_CRTP){ #MP_UNITS_API_NO_CRTP }
|
||||
|
||||
: [:octicons-tag-24: 2.2.0][cmake no crtp support] · :octicons-milestone-24: `AUTO`/`ON`/`OFF` (Default: `AUTO`)
|
||||
: [:octicons-tag-24: 2.2.0][cmake no crtp support] · :octicons-milestone-24: `AUTO`/`TRUE`/`FALSE` (Default: `AUTO`)
|
||||
|
||||
Removes the need for the usage of the CRTP idiom in the
|
||||
[`quantity_spec` definitions](../users_guide/framework_basics/systems_of_quantities.md#defining-quantities).
|
||||
|
@ -33,7 +33,7 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
inline constexpr struct smoot : named_unit<"smoot", mag<67> * usc::inch> {} smoot;
|
||||
inline constexpr struct smoot final : named_unit<"smoot", mag<67> * usc::inch> {} smoot;
|
||||
|
||||
int main()
|
||||
{
|
||||
@ -53,7 +53,7 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
inline constexpr struct smoot : named_unit<"smoot", mag<67> * usc::inch> {} smoot;
|
||||
inline constexpr struct smoot final : named_unit<"smoot", mag<67> * usc::inch> {} smoot;
|
||||
|
||||
int main()
|
||||
{
|
||||
@ -69,7 +69,7 @@ Output:
|
||||
Harvard Bridge length = 364.4 smoot (2034.6 ft, 620.14 m) ± 1 εar
|
||||
```
|
||||
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/zsW1f6Tn1)"
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/f8f4KnKh8)"
|
||||
|
||||
??? question "What is `smoot`?"
|
||||
|
||||
|
@ -7,7 +7,7 @@ tags:
|
||||
|
||||
# `avg_speed`
|
||||
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/EYo7879qd)"
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/TnqGa4sdn)"
|
||||
|
||||
Let's continue the previous example. This time, our purpose will not be to showcase as many
|
||||
library features as possible, but we will scope on different interfaces one can provide
|
||||
|
@ -6,7 +6,7 @@ tags:
|
||||
|
||||
# `hello_units`
|
||||
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/KKGGhKjqn)"
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/bT4GGPbef)"
|
||||
|
||||
This is a really simple example showcasing the features of the **mp-units** library.
|
||||
|
||||
@ -18,20 +18,20 @@ First, we either import the `mp_units` module or include the headers for:
|
||||
- text formatting and stream output support
|
||||
|
||||
```cpp title="hello_units.cpp" linenums="1"
|
||||
--8<-- "example/hello_units.cpp:28:40"
|
||||
--8<-- "example/hello_units.cpp:28:41"
|
||||
```
|
||||
|
||||
Also, to shorten the definitions, we "import" all the symbols from the `mp_units` namespace.
|
||||
|
||||
```cpp title="hello_units.cpp" linenums="13"
|
||||
--8<-- "example/hello_units.cpp:41:42"
|
||||
```cpp title="hello_units.cpp" linenums="14"
|
||||
--8<-- "example/hello_units.cpp:42:43"
|
||||
```
|
||||
|
||||
Next, we define a simple function that calculates the average speed based on the provided
|
||||
arguments of length and time:
|
||||
|
||||
```cpp title="hello_units.cpp" linenums="14"
|
||||
--8<-- "example/hello_units.cpp:43:46"
|
||||
```cpp title="hello_units.cpp" linenums="15"
|
||||
--8<-- "example/hello_units.cpp:44:47"
|
||||
```
|
||||
|
||||
The above function template takes any quantities implicitly convertible to `isq::length`
|
||||
@ -45,37 +45,37 @@ that its quantity type is implicitly convertible to `isq::speed`.
|
||||
type is beneficial for users of such a function as it provides more information
|
||||
of what to expect from a function than just using `auto`.
|
||||
|
||||
```cpp title="hello_units.cpp" linenums="18"
|
||||
--8<-- "example/hello_units.cpp:48:51"
|
||||
```cpp title="hello_units.cpp" linenums="19"
|
||||
--8<-- "example/hello_units.cpp:49:52"
|
||||
```
|
||||
|
||||
The above lines explicitly opt into using unit symbols from two systems of units.
|
||||
As this introduces a lot of short identifiers into the current scope, it is not done
|
||||
implicitly while including a header file.
|
||||
|
||||
```cpp title="hello_units.cpp" linenums="22"
|
||||
--8<-- "example/hello_units.cpp:53:59"
|
||||
```cpp title="hello_units.cpp" linenums="23"
|
||||
--8<-- "example/hello_units.cpp:54:60"
|
||||
```
|
||||
|
||||
- Lines `21` & `22` create a quantity of kind `isq::length / isq::time` with the numbers
|
||||
- Lines `23` & `24` create a quantity of kind `isq::length / isq::time` with the numbers
|
||||
and units provided. Such quantities can be converted or assigned to any other quantity
|
||||
with a matching kind.
|
||||
- Line `23` calls our function template with quantities of kind `isq::length` and
|
||||
- Line `25` calls our function template with quantities of kind `isq::length` and
|
||||
`isq::time` and number and units provided.
|
||||
- Line `24` explicitly provides quantity types of the quantities passed to a function template.
|
||||
- Line `26` explicitly provides quantity types of the quantities passed to a function template.
|
||||
This time, those will not be quantity kinds anymore and will have
|
||||
[more restrictive conversion rules](../framework_basics/simple_and_typed_quantities.md#quantity_cast-to-force-unsafe-conversions).
|
||||
- Line `25` changes the unit of a quantity `v3` to `m / s` in a
|
||||
- Line `27` changes the unit of a quantity `v3` to `m / s` in a
|
||||
[value-preserving way](../framework_basics/value_conversions.md#value-preserving-conversions)
|
||||
(floating-point representations are considered to be value-preserving).
|
||||
- Line `26` does a similar operation, but this time, it would also succeed for
|
||||
- Line `28` does a similar operation, but this time, it would also succeed for
|
||||
[value-truncating cases](../framework_basics/value_conversions.md#value-truncating-conversions)
|
||||
(if that was the case).
|
||||
- Line `27` does a [value-truncating conversion](../framework_basics/value_conversions.md#value-truncating-conversions)
|
||||
- Line `29` does a [value-truncating conversion](../framework_basics/value_conversions.md#value-truncating-conversions)
|
||||
of changing the underlying representation type from `double` to `int`.
|
||||
|
||||
```cpp title="hello_units.cpp" linenums="29"
|
||||
--8<-- "example/hello_units.cpp:61"
|
||||
```cpp title="hello_units.cpp" linenums="30"
|
||||
--8<-- "example/hello_units.cpp:62"
|
||||
```
|
||||
|
||||
The above presents [various ways to print a quantity](../framework_basics/text_output.md).
|
||||
|
@ -6,14 +6,14 @@ tags:
|
||||
|
||||
# `si_constants`
|
||||
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/sEqWcchdE)"
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/MevcK8vYT)"
|
||||
|
||||
The next example presents all the seven defining constants of the SI system. We can observe
|
||||
how [Faster-than-lightspeed Constants](../framework_basics/faster_than_lightspeed_constants.md)
|
||||
work in practice.
|
||||
|
||||
```cpp title="si_constants.cpp" linenums="1"
|
||||
--8<-- "example/si_constants.cpp:28:39"
|
||||
--8<-- "example/si_constants.cpp:28:40"
|
||||
```
|
||||
|
||||
As always, we start with the inclusion of all the needed header files. After that, for
|
||||
@ -21,8 +21,8 @@ the simplicity of this example, we
|
||||
[hack the character of quantities](../framework_basics/character_of_a_quantity.md#hacking-the-character)
|
||||
to be able to express vector quantities with simple scalar types.
|
||||
|
||||
```cpp title="si_constants.cpp" linenums="13"
|
||||
--8<-- "example/si_constants.cpp:41:"
|
||||
```cpp title="si_constants.cpp" linenums="14"
|
||||
--8<-- "example/si_constants.cpp:42:"
|
||||
```
|
||||
|
||||
The main part of the example prints all of the SI-defining constants. While analyzing the output of
|
||||
|
@ -97,15 +97,15 @@ enumeration can be appended to the `quantity_spec` describing such a quantity ty
|
||||
=== "C++23"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct position_vector : quantity_spec<length, quantity_character::vector> {} position_vector;
|
||||
inline constexpr struct displacement : quantity_spec<length, quantity_character::vector> {} displacement;
|
||||
inline constexpr struct position_vector final : quantity_spec<length, quantity_character::vector> {} position_vector;
|
||||
inline constexpr struct displacement final : quantity_spec<length, quantity_character::vector> {} displacement;
|
||||
```
|
||||
|
||||
=== "C++20"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct position_vector : quantity_spec<position_vector, length, quantity_character::vector> {} position_vector;
|
||||
inline constexpr struct displacement : quantity_spec<displacement, length, quantity_character::vector> {} displacement;
|
||||
inline constexpr struct position_vector final : quantity_spec<position_vector, length, quantity_character::vector> {} position_vector;
|
||||
inline constexpr struct displacement final : quantity_spec<displacement, length, quantity_character::vector> {} displacement;
|
||||
```
|
||||
|
||||
=== "Portable"
|
||||
@ -126,13 +126,13 @@ character override is needed):
|
||||
=== "C++23"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct velocity : quantity_spec<speed, position_vector / duration> {} velocity;
|
||||
inline constexpr struct velocity final : quantity_spec<speed, position_vector / duration> {} velocity;
|
||||
```
|
||||
|
||||
=== "C++20"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct velocity : quantity_spec<velocity, speed, position_vector / duration> {} velocity;
|
||||
inline constexpr struct velocity final : quantity_spec<velocity, speed, position_vector / duration> {} velocity;
|
||||
```
|
||||
|
||||
=== "Portable"
|
||||
|
@ -16,6 +16,8 @@ or derived [quantity](../../appendix/glossary.md#quantity):
|
||||
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).
|
||||
|
||||
All of the above dimensions have to be marked as `final`.
|
||||
|
||||
|
||||
### `DimensionOf<T, V>` { #DimensionOf }
|
||||
|
||||
@ -42,6 +44,8 @@ including:
|
||||
- Intermediate [derived quantity](../../appendix/glossary.md#derived-quantity) specifications being
|
||||
a result of a [quantity equations](../../appendix/glossary.md#quantity-equation) on other specifications.
|
||||
|
||||
All of the above quantity specifications have to be marked as `final`.
|
||||
|
||||
|
||||
### `QuantitySpecOf<T, V>` { #QuantitySpecOf }
|
||||
|
||||
@ -84,6 +88,8 @@ and when `T` is implicitly convertible to `V`.
|
||||
- [Derived unnamed units](../../appendix/glossary.md#derived-unit) being a result of a
|
||||
[unit equations](../../appendix/glossary.md#unit-equation) on other units.
|
||||
|
||||
All of the above units have to be marked as `final`.
|
||||
|
||||
!!! note
|
||||
|
||||
In the **mp-units** library, [physical constants are also implemented as units](faster_than_lightspeed_constants.md).
|
||||
@ -235,7 +241,7 @@ implicitly convertible from quantity specification `V`, which means that `V` mus
|
||||
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;
|
||||
inline constexpr struct mean_sea_level final : 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
|
||||
@ -328,7 +334,7 @@ for which an instantiation of `quantity_point_like_traits` type trait yields a v
|
||||
struct mp_units::quantity_point_like_traits<std::chrono::time_point<C, std::chrono::seconds>> {
|
||||
using T = std::chrono::time_point<C, std::chrono::seconds>;
|
||||
static constexpr auto reference = si::second;
|
||||
static constexpr struct point_origin : absolute_point_origin<isq::time> {} point_origin{};
|
||||
static constexpr struct point_origin final : absolute_point_origin<isq::time> {} point_origin{};
|
||||
using rep = std::chrono::seconds::rep;
|
||||
|
||||
[[nodiscard]] static constexpr convert_implicitly<quantity<reference, rep>> to_quantity(const T& qp)
|
||||
|
@ -60,8 +60,8 @@ For example:
|
||||
the following way:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct dim_length : base_dimension<"L"> {} dim_length;
|
||||
inline constexpr struct dim_time : base_dimension<"T"> {} dim_time;
|
||||
inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length;
|
||||
inline constexpr struct dim_time final : base_dimension<"T"> {} dim_time;
|
||||
```
|
||||
|
||||
[Derived dimensions](../../appendix/glossary.md#derived-dimension) are implicitly created
|
||||
@ -71,9 +71,9 @@ provided in the [quantity specification](../../appendix/glossary.md#quantity_spe
|
||||
=== "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;
|
||||
inline constexpr struct length final : quantity_spec<dim_length> {} length;
|
||||
inline constexpr struct time final : quantity_spec<dim_time> {} time;
|
||||
inline constexpr struct speed final : quantity_spec<length / time> {} speed;
|
||||
|
||||
static_assert(speed.dimension == dim_length / dim_time);
|
||||
```
|
||||
@ -81,9 +81,9 @@ provided in the [quantity specification](../../appendix/glossary.md#quantity_spe
|
||||
=== "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;
|
||||
inline constexpr struct length final : quantity_spec<length, dim_length> {} length;
|
||||
inline constexpr struct time final : quantity_spec<time, dim_time> {} time;
|
||||
inline constexpr struct speed final : quantity_spec<speed, length / time> {} speed;
|
||||
|
||||
static_assert(speed.dimension == dim_length / dim_time);
|
||||
```
|
||||
@ -183,17 +183,17 @@ 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;
|
||||
inline constexpr struct length final : quantity_spec<dim_length> {} length;
|
||||
inline constexpr struct height final : quantity_spec<length> {} height;
|
||||
inline constexpr struct speed final : 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;
|
||||
inline constexpr struct length final : quantity_spec<length, dim_length> {} length;
|
||||
inline constexpr struct height final : quantity_spec<height, length> {} height;
|
||||
inline constexpr struct speed final : quantity_spec<speed, length / time> {} speed;
|
||||
```
|
||||
|
||||
=== "Portable"
|
||||
@ -234,13 +234,13 @@ A unit can be defined by the user in one of the following ways:
|
||||
template<PrefixableUnit U> struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U{}> {};
|
||||
template<PrefixableUnit auto U> inline constexpr kilo_<decltype(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 second final : named_unit<"s", kind_of<isq::time>> {} second;
|
||||
inline constexpr struct minute final : named_unit<"min", mag<60> * second> {} minute;
|
||||
inline constexpr struct gram final : named_unit<"g", kind_of<isq::mass>> {} gram;
|
||||
inline constexpr auto kilogram = kilo<gram>;
|
||||
inline constexpr struct newton final : 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;
|
||||
inline constexpr struct speed_of_light_in_vacuum final : 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
|
||||
@ -346,13 +346,13 @@ 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;
|
||||
inline constexpr struct absolute_zero final : 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'150 * milli<kelvin>> {} ice_point;
|
||||
inline constexpr struct ice_point final : relative_point_origin<absolute_zero + 273'150 * milli<kelvin>> {} ice_point;
|
||||
```
|
||||
|
||||
|
||||
|
@ -113,7 +113,7 @@ that uses a unit that is proportional to the ratio of kilometers per megaparsecs
|
||||
units of _length_:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct hubble_constant :
|
||||
inline constexpr struct hubble_constant final :
|
||||
named_unit<{u8"H₀", "H_0"}, mag_ratio<701, 10> * si::kilo<si::metre> / si::second / si::mega<parsec>> {} hubble_constant;
|
||||
```
|
||||
|
||||
@ -158,9 +158,9 @@ Besides the unit `one`, there are a few other scaled units predefined in the lib
|
||||
with dimensionless quantities:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct percent : named_unit<"%", mag_ratio<1, 100> * one> {} percent;
|
||||
inline constexpr struct per_mille : named_unit<{u8"‰", "%o"}, mag_ratio<1, 1000> * one> {} per_mille;
|
||||
inline constexpr struct parts_per_million : named_unit<"ppm", mag_ratio<1, 1'000'000> * one> {} parts_per_million;
|
||||
inline constexpr struct percent final : named_unit<"%", mag_ratio<1, 100> * one> {} percent;
|
||||
inline constexpr struct per_mille final : named_unit<{u8"‰", "%o"}, mag_ratio<1, 1000> * one> {} per_mille;
|
||||
inline constexpr struct parts_per_million final : named_unit<"ppm", mag_ratio<1, 1'000'000> * one> {} parts_per_million;
|
||||
inline constexpr auto ppm = parts_per_million;
|
||||
```
|
||||
|
||||
@ -217,17 +217,17 @@ to the quantity specification:
|
||||
=== "C++23"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct angular_measure : quantity_spec<dimensionless, arc_length / radius, is_kind> {} angular_measure;
|
||||
inline constexpr struct solid_angular_measure : quantity_spec<dimensionless, area / pow<2>(radius), is_kind> {} solid_angular_measure;
|
||||
inline constexpr struct storage_capacity : quantity_spec<dimensionless, is_kind> {} storage_capacity;
|
||||
inline constexpr struct angular_measure final : quantity_spec<dimensionless, arc_length / radius, is_kind> {} angular_measure;
|
||||
inline constexpr struct solid_angular_measure final : quantity_spec<dimensionless, area / pow<2>(radius), is_kind> {} solid_angular_measure;
|
||||
inline constexpr struct storage_capacity final : quantity_spec<dimensionless, is_kind> {} storage_capacity;
|
||||
```
|
||||
|
||||
=== "C++20"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct angular_measure : quantity_spec<angular_measure, dimensionless, arc_length / radius, is_kind> {} angular_measure;
|
||||
inline constexpr struct solid_angular_measure : quantity_spec<solid_angular_measure, dimensionless, area / pow<2>(radius), is_kind> {} solid_angular_measure;
|
||||
inline constexpr struct storage_capacity : quantity_spec<storage_capacity, dimensionless, is_kind> {} storage_capacity;
|
||||
inline constexpr struct angular_measure final : quantity_spec<angular_measure, dimensionless, arc_length / radius, is_kind> {} angular_measure;
|
||||
inline constexpr struct solid_angular_measure final : quantity_spec<solid_angular_measure, dimensionless, area / pow<2>(radius), is_kind> {} solid_angular_measure;
|
||||
inline constexpr struct storage_capacity final : quantity_spec<storage_capacity, dimensionless, is_kind> {} storage_capacity;
|
||||
```
|
||||
|
||||
=== "Portable"
|
||||
@ -242,9 +242,9 @@ With the above, we can constrain `radian`, `steradian`, and `bit` to be allowed
|
||||
specific quantity kinds only:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct radian : named_unit<"rad", metre / metre, kind_of<isq::angular_measure>> {} radian;
|
||||
inline constexpr struct steradian : named_unit<"sr", square(metre) / square(metre), kind_of<isq::solid_angular_measure>> {} steradian;
|
||||
inline constexpr struct bit : named_unit<"bit", one, kind_of<storage_capacity>> {} bit;
|
||||
inline constexpr struct radian final : named_unit<"rad", metre / metre, kind_of<isq::angular_measure>> {} radian;
|
||||
inline constexpr struct steradian final : named_unit<"sr", square(metre) / square(metre), kind_of<isq::solid_angular_measure>> {} steradian;
|
||||
inline constexpr struct bit final : named_unit<"bit", one, kind_of<storage_capacity>> {} bit;
|
||||
```
|
||||
|
||||
but still allow the usage of `one` and its scaled versions for such quantities.
|
||||
|
@ -39,12 +39,12 @@ namespace si {
|
||||
|
||||
namespace si2019 {
|
||||
|
||||
inline constexpr struct speed_of_light_in_vacuum :
|
||||
inline constexpr struct speed_of_light_in_vacuum final :
|
||||
named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
|
||||
|
||||
} // namespace si2019
|
||||
|
||||
inline constexpr struct magnetic_constant :
|
||||
inline constexpr struct magnetic_constant final :
|
||||
named_unit<{u8"μ₀", "u_0"}, mag<4> * mag_pi * mag_power<10, -7> * henry / metre> {} magnetic_constant;
|
||||
|
||||
} // namespace mp_units::si
|
||||
|
@ -6,8 +6,8 @@ The **mp-units** library decided to use a rather unusual pattern to define entit
|
||||
Here is how we define `metre` and `second` [SI](../../appendix/glossary.md#si) base units:
|
||||
|
||||
```cpp
|
||||
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 metre final : named_unit<"m", kind_of<isq::length>> {} metre;
|
||||
inline constexpr struct second final : named_unit<"s", kind_of<isq::time>> {} second;
|
||||
```
|
||||
|
||||
Please note that the above reuses the same identifier for a type and its value. The rationale
|
||||
@ -94,9 +94,9 @@ the value-based [unit equation](../../appendix/glossary.md#unit-equation) to a c
|
||||
definition:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
||||
inline constexpr struct pascal : named_unit<"Pa", newton / square(metre)> {} pascal;
|
||||
inline constexpr struct joule : named_unit<"J", newton * metre> {} joule;
|
||||
inline constexpr struct newton final : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
||||
inline constexpr struct pascal final : named_unit<"Pa", newton / square(metre)> {} pascal;
|
||||
inline constexpr struct joule final : named_unit<"J", newton * metre> {} joule;
|
||||
```
|
||||
|
||||
|
||||
|
@ -316,13 +316,13 @@ Let's see another example:
|
||||
using namespace mp_units;
|
||||
|
||||
// add a custom quantity type of kind isq::length
|
||||
inline constexpr struct horizontal_length
|
||||
: quantity_spec<isq::length> {} horizontal_length;
|
||||
inline constexpr struct horizontal_length final :
|
||||
quantity_spec<isq::length> {} horizontal_length;
|
||||
|
||||
// add a custom derived quantity type of kind isq::area
|
||||
// with a constrained quantity equation
|
||||
inline constexpr struct horizontal_area
|
||||
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||
inline constexpr struct horizontal_area final :
|
||||
quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||
|
||||
class StorageTank {
|
||||
quantity<horizontal_area[square(si::metre)]> base_;
|
||||
@ -429,13 +429,13 @@ Let's see another example:
|
||||
using namespace mp_units;
|
||||
|
||||
// add a custom quantity type of kind isq::length
|
||||
inline constexpr struct horizontal_length
|
||||
: quantity_spec<isq::length> {} horizontal_length;
|
||||
inline constexpr struct horizontal_length final :
|
||||
quantity_spec<isq::length> {} horizontal_length;
|
||||
|
||||
// add a custom derived quantity type of kind isq::area
|
||||
// with a constrained quantity equation
|
||||
inline constexpr struct horizontal_area
|
||||
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||
inline constexpr struct horizontal_area final :
|
||||
quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||
|
||||
class StorageTank {
|
||||
quantity<horizontal_area[square(si::metre)]> base_;
|
||||
|
@ -148,45 +148,45 @@ For example, here is how the above quantity kind tree can be modeled in the libr
|
||||
=== "C++23"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct length : quantity_spec<dim_length> {} length;
|
||||
inline constexpr struct width : quantity_spec<length> {} width;
|
||||
inline constexpr struct length final : quantity_spec<dim_length> {} length;
|
||||
inline constexpr struct width final : quantity_spec<length> {} width;
|
||||
inline constexpr auto breadth = width;
|
||||
inline constexpr struct height : quantity_spec<length> {} height;
|
||||
inline constexpr struct height final : quantity_spec<length> {} height;
|
||||
inline constexpr auto depth = height;
|
||||
inline constexpr auto altitude = height;
|
||||
inline constexpr struct thickness : quantity_spec<width> {} thickness;
|
||||
inline constexpr struct diameter : quantity_spec<width> {} diameter;
|
||||
inline constexpr struct radius : quantity_spec<width> {} radius;
|
||||
inline constexpr struct radius_of_curvature : quantity_spec<radius> {} radius_of_curvature;
|
||||
inline constexpr struct path_length : quantity_spec<length> {} path_length;
|
||||
inline constexpr struct thickness final : quantity_spec<width> {} thickness;
|
||||
inline constexpr struct diameter final : quantity_spec<width> {} diameter;
|
||||
inline constexpr struct radius final : quantity_spec<width> {} radius;
|
||||
inline constexpr struct radius_of_curvature final : quantity_spec<radius> {} radius_of_curvature;
|
||||
inline constexpr struct path_length final : quantity_spec<length> {} path_length;
|
||||
inline constexpr auto arc_length = path_length;
|
||||
inline constexpr struct distance : quantity_spec<path_length> {} distance;
|
||||
inline constexpr struct radial_distance : quantity_spec<distance> {} radial_distance;
|
||||
inline constexpr struct wavelength : quantity_spec<length> {} wavelength;
|
||||
inline constexpr struct position_vector : quantity_spec<length, quantity_character::vector> {} position_vector;
|
||||
inline constexpr struct displacement : quantity_spec<length, quantity_character::vector> {} displacement;
|
||||
inline constexpr struct distance final : quantity_spec<path_length> {} distance;
|
||||
inline constexpr struct radial_distance final : quantity_spec<distance> {} radial_distance;
|
||||
inline constexpr struct wavelength final : quantity_spec<length> {} wavelength;
|
||||
inline constexpr struct position_vector final : quantity_spec<length, quantity_character::vector> {} position_vector;
|
||||
inline constexpr struct displacement final : quantity_spec<length, quantity_character::vector> {} displacement;
|
||||
```
|
||||
|
||||
=== "C++20"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct length : quantity_spec<length, dim_length> {} length;
|
||||
inline constexpr struct width : quantity_spec<width, length> {} width;
|
||||
inline constexpr struct length final : quantity_spec<length, dim_length> {} length;
|
||||
inline constexpr struct width final : quantity_spec<width, length> {} width;
|
||||
inline constexpr auto breadth = width;
|
||||
inline constexpr struct height : quantity_spec<height, length> {} height;
|
||||
inline constexpr struct height final : quantity_spec<height, length> {} height;
|
||||
inline constexpr auto depth = height;
|
||||
inline constexpr auto altitude = height;
|
||||
inline constexpr struct thickness : quantity_spec<thickness, width> {} thickness;
|
||||
inline constexpr struct diameter : quantity_spec<diameter, width> {} diameter;
|
||||
inline constexpr struct radius : quantity_spec<radius, width> {} radius;
|
||||
inline constexpr struct radius_of_curvature : quantity_spec<radius_of_curvature, radius> {} radius_of_curvature;
|
||||
inline constexpr struct path_length : quantity_spec<path_length, length> {} path_length;
|
||||
inline constexpr struct thickness final : quantity_spec<thickness, width> {} thickness;
|
||||
inline constexpr struct diameter final : quantity_spec<diameter, width> {} diameter;
|
||||
inline constexpr struct radius final : quantity_spec<radius, width> {} radius;
|
||||
inline constexpr struct radius_of_curvature final : quantity_spec<radius_of_curvature, radius> {} radius_of_curvature;
|
||||
inline constexpr struct path_length final : quantity_spec<path_length, length> {} path_length;
|
||||
inline constexpr auto arc_length = path_length;
|
||||
inline constexpr struct distance : quantity_spec<distance, path_length> {} distance;
|
||||
inline constexpr struct radial_distance : quantity_spec<radial_distance, distance> {} radial_distance;
|
||||
inline constexpr struct wavelength : quantity_spec<wavelength, length> {} wavelength;
|
||||
inline constexpr struct position_vector : quantity_spec<position_vector, length, quantity_character::vector> {} position_vector;
|
||||
inline constexpr struct displacement : quantity_spec<displacement, length, quantity_character::vector> {} displacement;
|
||||
inline constexpr struct distance final : quantity_spec<distance, path_length> {} distance;
|
||||
inline constexpr struct radial_distance final : quantity_spec<radial_distance, distance> {} radial_distance;
|
||||
inline constexpr struct wavelength final : quantity_spec<wavelength, length> {} wavelength;
|
||||
inline constexpr struct position_vector final : quantity_spec<position_vector, length, quantity_character::vector> {} position_vector;
|
||||
inline constexpr struct displacement final : quantity_spec<displacement, length, quantity_character::vector> {} displacement;
|
||||
```
|
||||
|
||||
=== "Portable"
|
||||
|
@ -26,7 +26,7 @@ this is expressed by associating a quantity kind (that we discussed in detail in
|
||||
previous chapter) with a unit that is used to express it:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct metre : named_unit<"m", kind_of<isq::length>> {} metre;
|
||||
inline constexpr struct metre final : named_unit<"m", kind_of<isq::length>> {} metre;
|
||||
```
|
||||
|
||||
!!! important
|
||||
@ -67,7 +67,7 @@ of a specific predefined [unit equation](../../appendix/glossary.md#unit-equatio
|
||||
For example, a unit of _power_ quantity is defined in the library as:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct watt : named_unit<"W", joule / second> {} watt;
|
||||
inline constexpr struct watt final : named_unit<"W", joule / second> {} watt;
|
||||
```
|
||||
|
||||
However, a _power_ quantity can be expressed in other units as well. For example,
|
||||
@ -110,8 +110,8 @@ The library allows constraining such units to work only with quantities of a spe
|
||||
the following way:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct hertz : named_unit<"Hz", one / second, kind_of<isq::frequency>> {} hertz;
|
||||
inline constexpr struct becquerel : named_unit<"Bq", one / second, kind_of<isq::activity>> {} becquerel;
|
||||
inline constexpr struct hertz final : named_unit<"Hz", one / second, kind_of<isq::frequency>> {} hertz;
|
||||
inline constexpr struct becquerel final : named_unit<"Bq", one / second, kind_of<isq::activity>> {} becquerel;
|
||||
```
|
||||
|
||||
With the above, `hertz` can only be used with _frequencies_, while `becquerel` should only be used with
|
||||
@ -168,25 +168,25 @@ be explicitly expressed with predefined SI prefixes. Those include units like mi
|
||||
electronvolt:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct minute : named_unit<"min", mag<60> * si::second> {} minute;
|
||||
inline constexpr struct hour : named_unit<"h", mag<60> * minute> {} hour;
|
||||
inline constexpr struct electronvolt : named_unit<"eV", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * si::joule> {} electronvolt;
|
||||
inline constexpr struct minute final : named_unit<"min", mag<60> * si::second> {} minute;
|
||||
inline constexpr struct hour final : named_unit<"h", mag<60> * minute> {} hour;
|
||||
inline constexpr struct electronvolt final : named_unit<"eV", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * si::joule> {} electronvolt;
|
||||
```
|
||||
|
||||
Also, units of other [systems of units](../../appendix/glossary.md#system-of-units) are often defined
|
||||
in terms of scaled versions of the SI units. For example, the international yard is defined as:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct yard : named_unit<"yd", mag_ratio<9'144, 10'000> * si::metre> {} yard;
|
||||
inline constexpr struct yard final : named_unit<"yd", mag_ratio<9'144, 10'000> * si::metre> {} yard;
|
||||
```
|
||||
|
||||
For some units, a magnitude might also be irrational. The best example here is a `degree` which
|
||||
is defined using a floating-point magnitude having a factor of the number π (Pi):
|
||||
|
||||
```cpp
|
||||
inline constexpr struct mag_pi : magnitude<std::numbers::pi_v<long double>> {} mag_pi;
|
||||
inline constexpr struct mag_pi final : magnitude<std::numbers::pi_v<long double>> {} mag_pi;
|
||||
```
|
||||
|
||||
```cpp
|
||||
inline constexpr struct degree : named_unit<{u8"°", "deg"}, mag_pi / mag<180> * si::radian> {} degree;
|
||||
inline constexpr struct degree final : named_unit<{u8"°", "deg"}, mag_pi / mag<180> * si::radian> {} degree;
|
||||
```
|
||||
|
@ -33,30 +33,30 @@ and units of derived quantities.
|
||||
=== "Dimensions"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct dim_length : base_dimension<"L"> {} dim_length;
|
||||
inline constexpr struct dim_mass : base_dimension<"M"> {} dim_mass;
|
||||
inline constexpr struct dim_time : base_dimension<"T"> {} dim_time;
|
||||
inline constexpr struct dim_electric_current : base_dimension<"I"> {} dim_electric_current;
|
||||
inline constexpr struct dim_thermodynamic_temperature : base_dimension<{u8"Θ", "O"}> {} dim_thermodynamic_temperature;
|
||||
inline constexpr struct dim_amount_of_substance : base_dimension<"N"> {} dim_amount_of_substance;
|
||||
inline constexpr struct dim_luminous_intensity : base_dimension<"J"> {} dim_luminous_intensity;
|
||||
inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length;
|
||||
inline constexpr struct dim_mass final : base_dimension<"M"> {} dim_mass;
|
||||
inline constexpr struct dim_time final : base_dimension<"T"> {} dim_time;
|
||||
inline constexpr struct dim_electric_current final : base_dimension<"I"> {} dim_electric_current;
|
||||
inline constexpr struct dim_thermodynamic_temperature final : base_dimension<{u8"Θ", "O"}> {} dim_thermodynamic_temperature;
|
||||
inline constexpr struct dim_amount_of_substance final : base_dimension<"N"> {} dim_amount_of_substance;
|
||||
inline constexpr struct dim_luminous_intensity final : base_dimension<"J"> {} dim_luminous_intensity;
|
||||
```
|
||||
|
||||
=== "Units"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct second : named_unit<"s", kind_of<isq::time>> {} second;
|
||||
inline constexpr struct metre : named_unit<"m", kind_of<isq::length>> {} metre;
|
||||
inline constexpr struct gram : named_unit<"g", kind_of<isq::mass>> {} gram;
|
||||
inline constexpr struct kilogram : decltype(kilo<gram>) {} kilogram;
|
||||
inline constexpr struct second final : named_unit<"s", kind_of<isq::time>> {} second;
|
||||
inline constexpr struct metre final : named_unit<"m", kind_of<isq::length>> {} metre;
|
||||
inline constexpr struct gram final : named_unit<"g", kind_of<isq::mass>> {} gram;
|
||||
inline constexpr auto kilogram = kilo<gram>;
|
||||
|
||||
inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
||||
inline constexpr struct joule : named_unit<"J", newton * metre> {} joule;
|
||||
inline constexpr struct watt : named_unit<"W", joule / second> {} watt;
|
||||
inline constexpr struct coulomb : named_unit<"C", ampere * second> {} coulomb;
|
||||
inline constexpr struct volt : named_unit<"V", watt / ampere> {} volt;
|
||||
inline constexpr struct farad : named_unit<"F", coulomb / volt> {} farad;
|
||||
inline constexpr struct ohm : named_unit<{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
||||
inline constexpr struct newton final : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
||||
inline constexpr struct joule final : named_unit<"J", newton * metre> {} joule;
|
||||
inline constexpr struct watt final : named_unit<"W", joule / second> {} watt;
|
||||
inline constexpr struct coulomb final : named_unit<"C", ampere * second> {} coulomb;
|
||||
inline constexpr struct volt final : named_unit<"V", watt / ampere> {} volt;
|
||||
inline constexpr struct farad final : named_unit<"F", coulomb / volt> {} farad;
|
||||
inline constexpr struct ohm final : named_unit<{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
||||
```
|
||||
|
||||
=== "Prefixes"
|
||||
@ -75,13 +75,13 @@ and units of derived quantities.
|
||||
=== "Constants"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct hyperfine_structure_transition_frequency_of_cs : named_unit<{u8"Δν_Cs", "dv_Cs"}, mag<9'192'631'770> * hertz> {} hyperfine_structure_transition_frequency_of_cs;
|
||||
inline constexpr struct speed_of_light_in_vacuum : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
|
||||
inline constexpr struct planck_constant : named_unit<"h", mag_ratio<662'607'015, 100'000'000> * mag_power<10, -34> * joule * second> {} planck_constant;
|
||||
inline constexpr struct elementary_charge : named_unit<"e", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * coulomb> {} elementary_charge;
|
||||
inline constexpr struct boltzmann_constant : named_unit<"k", mag_ratio<1'380'649, 1'000'000> * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant;
|
||||
inline constexpr struct avogadro_constant : named_unit<"N_A", mag_ratio<602'214'076, 100'000'000> * mag_power<10, 23> / mole> {} avogadro_constant;
|
||||
inline constexpr struct luminous_efficacy : named_unit<"K_cd", mag<683> * lumen / watt> {} luminous_efficacy;
|
||||
inline constexpr struct hyperfine_structure_transition_frequency_of_cs final : named_unit<{u8"Δν_Cs", "dv_Cs"}, mag<9'192'631'770> * hertz> {} hyperfine_structure_transition_frequency_of_cs;
|
||||
inline constexpr struct speed_of_light_in_vacuum final : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum;
|
||||
inline constexpr struct planck_constant final : named_unit<"h", mag_ratio<662'607'015, 100'000'000> * mag_power<10, -34> * joule * second> {} planck_constant;
|
||||
inline constexpr struct elementary_charge final : named_unit<"e", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * coulomb> {} elementary_charge;
|
||||
inline constexpr struct boltzmann_constant final : named_unit<"k", mag_ratio<1'380'649, 1'000'000> * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant;
|
||||
inline constexpr struct avogadro_constant final : named_unit<"N_A", mag_ratio<602'214'076, 100'000'000> * mag_power<10, 23> / mole> {} avogadro_constant;
|
||||
inline constexpr struct luminous_efficacy final : named_unit<"K_cd", mag<683> * lumen / watt> {} luminous_efficacy;
|
||||
```
|
||||
|
||||
!!! important
|
||||
@ -105,7 +105,7 @@ and units of derived quantities.
|
||||
template name to initialize it with two symbols:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct ohm : named_unit<symbol_text{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
||||
inline constexpr struct ohm final : named_unit<symbol_text{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
||||
```
|
||||
|
||||
|
||||
|
@ -172,7 +172,7 @@ origin.
|
||||
{style="width:80%;display: block;margin: 0 auto;"}
|
||||
|
||||
```cpp
|
||||
inline constexpr struct origin : absolute_point_origin<origin, isq::distance> {} origin;
|
||||
inline constexpr struct origin final : absolute_point_origin<isq::distance> {} origin;
|
||||
|
||||
// quantity_point<si::metre, origin> qp1{100 * m}; // Compile-time error
|
||||
// quantity_point<si::metre, origin> qp2{120 * m}; // Compile-time error
|
||||
@ -197,14 +197,6 @@ assert(origin - qp2 == -120 * m);
|
||||
// assert(origin - origin == 0 * m); // Compile-time error
|
||||
```
|
||||
|
||||
!!! info
|
||||
|
||||
The `absolute_point_origin` class template uses the CRTP idiom to enforce the uniqueness of
|
||||
such a type. You should pass the type of a derived class as the first argument of the template
|
||||
instantiation.
|
||||
|
||||
*[CRTP]: Curiously Recurring Template Parameter
|
||||
|
||||
We can't construct a quantity point directly from the quantity anymore when a custom, named origin
|
||||
is used. To prevent potential safety and maintenance issues, we always need to
|
||||
explicitly provide both a compatible origin and a quantity measured from it to construct a quantity
|
||||
@ -249,8 +241,8 @@ type and unit is being used:
|
||||
{style="width:80%;display: block;margin: 0 auto;"}
|
||||
|
||||
```cpp
|
||||
inline constexpr struct origin1 : absolute_point_origin<origin1, isq::distance> {} origin1;
|
||||
inline constexpr struct origin2 : absolute_point_origin<origin2, isq::distance> {} origin2;
|
||||
inline constexpr struct origin1 final : absolute_point_origin<isq::distance> {} origin1;
|
||||
inline constexpr struct origin2 final : absolute_point_origin<isq::distance> {} origin2;
|
||||
|
||||
quantity_point qp1 = origin1 + 100 * m;
|
||||
quantity_point qp2 = origin2 + 120 * m;
|
||||
@ -284,10 +276,10 @@ For such cases, relative point origins should be used:
|
||||
{style="width:80%;display: block;margin: 0 auto;"}
|
||||
|
||||
```cpp
|
||||
inline constexpr struct A : absolute_point_origin<A, isq::distance> {} A;
|
||||
inline constexpr struct B : relative_point_origin<A + 10 * m> {} B;
|
||||
inline constexpr struct C : relative_point_origin<B + 10 * m> {} C;
|
||||
inline constexpr struct D : relative_point_origin<A + 30 * m> {} D;
|
||||
inline constexpr struct A final : absolute_point_origin<isq::distance> {} A;
|
||||
inline constexpr struct B final : relative_point_origin<A + 10 * m> {} B;
|
||||
inline constexpr struct C final : relative_point_origin<B + 10 * m> {} C;
|
||||
inline constexpr struct D final : relative_point_origin<A + 30 * m> {} D;
|
||||
|
||||
quantity_point qp1 = C + 100 * m;
|
||||
quantity_point qp2 = D + 120 * m;
|
||||
@ -392,17 +384,17 @@ point origins for this purpose:
|
||||
```cpp
|
||||
namespace si {
|
||||
|
||||
inline constexpr struct absolute_zero : absolute_point_origin<absolute_zero, isq::thermodynamic_temperature> {} absolute_zero;
|
||||
inline constexpr struct zeroth_kelvin : decltype(absolute_zero) {} zeroth_kelvin;
|
||||
inline constexpr struct absolute_zero final : absolute_point_origin<isq::thermodynamic_temperature> {} absolute_zero;
|
||||
inline constexpr auto zeroth_kelvin = absolute_zero;
|
||||
|
||||
inline constexpr struct ice_point : relative_point_origin<quantity_point{273'150 * milli<kelvin>}> {} ice_point;
|
||||
inline constexpr struct zeroth_degree_Celsius : decltype(ice_point) {} zeroth_degree_Celsius;
|
||||
inline constexpr struct ice_point final : relative_point_origin<quantity_point{273'150 * milli<kelvin>}> {} ice_point;
|
||||
inline constexpr auto zeroth_degree_Celsius = ice_point;
|
||||
|
||||
}
|
||||
|
||||
namespace usc {
|
||||
|
||||
inline constexpr struct zeroth_degree_Fahrenheit :
|
||||
inline constexpr struct zeroth_degree_Fahrenheit final :
|
||||
relative_point_origin<quantity_point{-32 * (mag_ratio<5, 9> * si::degree_Celsius)}> {} zeroth_degree_Fahrenheit;
|
||||
|
||||
}
|
||||
@ -426,16 +418,16 @@ definitions:
|
||||
```cpp
|
||||
namespace si {
|
||||
|
||||
inline constexpr struct kelvin :
|
||||
inline constexpr struct kelvin final :
|
||||
named_unit<"K", kind_of<isq::thermodynamic_temperature>, zeroth_kelvin> {} kelvin;
|
||||
inline constexpr struct degree_Celsius :
|
||||
inline constexpr struct degree_Celsius final :
|
||||
named_unit<{u8"°C", "`C"}, kelvin, zeroth_degree_Celsius> {} degree_Celsius;
|
||||
|
||||
}
|
||||
|
||||
namespace usc {
|
||||
|
||||
inline constexpr struct degree_Fahrenheit :
|
||||
inline constexpr struct degree_Fahrenheit final :
|
||||
named_unit<{u8"°F", "`F"}, mag_ratio<5, 9> * si::degree_Celsius,
|
||||
zeroth_degree_Fahrenheit> {} degree_Fahrenheit;
|
||||
|
||||
@ -481,7 +473,7 @@ the following way:
|
||||
{style="width:80%;display: block;margin: 0 auto;"}
|
||||
|
||||
```cpp
|
||||
constexpr struct room_reference_temp : relative_point_origin<quantity_point{21 * deg_C}> {} room_reference_temp;
|
||||
constexpr struct room_reference_temp final : relative_point_origin<quantity_point{21 * deg_C}> {} room_reference_temp;
|
||||
using room_temp = quantity_point<isq::Celsius_temperature[deg_C], room_reference_temp>;
|
||||
|
||||
constexpr auto step_delta = isq::Celsius_temperature(0.5 * deg_C);
|
||||
|
@ -85,11 +85,11 @@ the `value_cast<U, Rep>(q)` which always returns the most precise result:
|
||||
=== "C++23"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency;
|
||||
inline constexpr struct currency : quantity_spec<dim_currency> {} currency;
|
||||
inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency;
|
||||
inline constexpr struct currency final : quantity_spec<dim_currency> {} currency;
|
||||
|
||||
inline constexpr struct us_dollar : named_unit<"USD", kind_of<currency>> {} us_dollar;
|
||||
inline constexpr struct scaled_us_dollar : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
|
||||
inline constexpr struct us_dollar final : named_unit<"USD", kind_of<currency>> {} us_dollar;
|
||||
inline constexpr struct scaled_us_dollar final : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
|
||||
|
||||
namespace unit_symbols {
|
||||
|
||||
@ -105,11 +105,11 @@ the `value_cast<U, Rep>(q)` which always returns the most precise result:
|
||||
=== "C++20"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency;
|
||||
inline constexpr struct currency : quantity_spec<currency, dim_currency> {} currency;
|
||||
inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency;
|
||||
inline constexpr struct currency final : quantity_spec<currency, dim_currency> {} currency;
|
||||
|
||||
inline constexpr struct us_dollar : named_unit<"USD", kind_of<currency>> {} us_dollar;
|
||||
inline constexpr struct scaled_us_dollar : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
|
||||
inline constexpr struct us_dollar final : named_unit<"USD", kind_of<currency>> {} us_dollar;
|
||||
inline constexpr struct scaled_us_dollar final : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
|
||||
|
||||
namespace unit_symbols {
|
||||
|
||||
@ -125,11 +125,11 @@ the `value_cast<U, Rep>(q)` which always returns the most precise result:
|
||||
=== "Portable"
|
||||
|
||||
```cpp
|
||||
inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency;
|
||||
inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency;
|
||||
QUANTITY_SPEC(currency, dim_currency);
|
||||
|
||||
inline constexpr struct us_dollar : named_unit<"USD", kind_of<currency>> {} us_dollar;
|
||||
inline constexpr struct scaled_us_dollar : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
|
||||
inline constexpr struct us_dollar final : named_unit<"USD", kind_of<currency>> {} us_dollar;
|
||||
inline constexpr struct scaled_us_dollar final : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
|
||||
|
||||
namespace unit_symbols {
|
||||
|
||||
|
@ -256,8 +256,8 @@ include the _mp-units/systems/si/chrono.h_ file to benefit from it. This file pr
|
||||
to the `std::chrono` abstractions:
|
||||
|
||||
```cpp
|
||||
inline constexpr struct ts_origin : relative_point_origin<chrono_point_origin<system_clock> + 1 * h> {} ts_origin;
|
||||
inline constexpr struct my_origin : absolute_point_origin<my_origin, isq::time> {} my_origin;
|
||||
inline constexpr struct ts_origin final : relative_point_origin<chrono_point_origin<system_clock> + 1 * h> {} ts_origin;
|
||||
inline constexpr struct my_origin final : absolute_point_origin<isq::time> {} my_origin;
|
||||
|
||||
quantity_point qp1 = sys_seconds{1s};
|
||||
auto tp1 = to_chrono_time_point(qp1); // OK
|
||||
|
@ -29,7 +29,7 @@ your code using **mp-units**:
|
||||
|
||||
// ...
|
||||
|
||||
inline constexpr struct horizontal_length : quantity_spec<isq::length> {} horizontal_length;
|
||||
inline constexpr struct horizontal_length final : quantity_spec<isq::length> {} horizontal_length;
|
||||
|
||||
// ...
|
||||
|
||||
@ -45,7 +45,7 @@ your code using **mp-units**:
|
||||
|
||||
// ...
|
||||
|
||||
inline constexpr struct horizontal_length : quantity_spec<horizontal_length, isq::length> {} horizontal_length;
|
||||
inline constexpr struct horizontal_length final : quantity_spec<horizontal_length, isq::length> {} horizontal_length;
|
||||
|
||||
// ...
|
||||
|
||||
@ -65,7 +65,7 @@ your code using **mp-units**:
|
||||
|
||||
// ...
|
||||
|
||||
inline constexpr struct horizontal_length : quantity_spec<horizontal_length, isq::length> {} horizontal_length;
|
||||
inline constexpr struct horizontal_length final : quantity_spec<horizontal_length, isq::length> {} horizontal_length;
|
||||
|
||||
// ...
|
||||
|
||||
@ -85,7 +85,7 @@ your code using **mp-units**:
|
||||
|
||||
// ...
|
||||
|
||||
inline constexpr struct horizontal_length : quantity_spec<horizontal_length, isq::length> {} horizontal_length;
|
||||
inline constexpr struct horizontal_length final : quantity_spec<horizontal_length, isq::length> {} horizontal_length;
|
||||
|
||||
// ...
|
||||
|
||||
@ -96,6 +96,7 @@ your code using **mp-units**:
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <mp-units/ext/format.h>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
#include <mp-units/compat_macros.h>
|
||||
import mp_units;
|
||||
@ -157,3 +158,30 @@ from additional features provided with the library).
|
||||
This macro resolves to either the `std` or `fmt` namespace, depending on the value of
|
||||
[MP_UNITS_API_STD_FORMAT](../../getting_started/installation_and_usage.md#MP_UNITS_API_STD_FORMAT)
|
||||
CMake option.
|
||||
|
||||
To include the header files of the underlying text formatting framework, the following include
|
||||
should be used:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/ext/format.h>
|
||||
```
|
||||
|
||||
### Contracts
|
||||
|
||||
The mp-units library internally does contract checking by default. It can be disabled with a Conan
|
||||
or CMake option. However, when enabled, it can use either [gsl-lite](https://github.com/gsl-lite/gsl-lite)
|
||||
or [ms-gsl](https://github.com/microsoft/GSL). To write a code that is independent from the
|
||||
underlying framework, the following preprocessor macros are exposed:
|
||||
|
||||
- `MP_UNITS_EXPECTS(expr)`
|
||||
- `MP_UNITS_EXPECTS_DEBUG(expr)`
|
||||
- `MP_UNITS_ASSERT(expr)`
|
||||
- `MP_UNITS_ASSERT_DEBUG(expr)`
|
||||
|
||||
Their meaning is consistent with respective [gsl-lite](https://github.com/gsl-lite/gsl-lite?tab=readme-ov-file#contract-checking-configuration-macros).
|
||||
|
||||
Also, to include the header files of the underlying framework, the following include should be used:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/ext/contracts.h>
|
||||
```
|
||||
|
Reference in New Issue
Block a user