mirror of
https://github.com/mpusz/mp-units.git
synced 2025-06-25 01:01:33 +02:00
Merge branch 'master' into feature/more-value-casts
This commit is contained in:
16
CHANGELOG.md
16
CHANGELOG.md
@ -5,11 +5,12 @@
|
||||
### 2.2.0 <small>WIP</small> { id="2.2.0" }
|
||||
|
||||
- (!) feat: C++ modules support added by [@JohelEGP](https://github.com/JohelEGP)
|
||||
- (!) feat: formatting grammar improved and units formatting support added
|
||||
- (!) feat: New formatting specification implemented
|
||||
- (!) feat: `has_unit_symbol` support removed
|
||||
- (!) feat: ABI concerns resolved with introduction of u8 strings for symbols
|
||||
- (!) feat: API-related Conan, CMake, and preprocessor options redesigned
|
||||
- (!) feat: :boom: `core.h` removed
|
||||
- (!) feat: `core.h` removed
|
||||
- (!) feat: from now on units, dimensions, quantity specifications, and point origins have to be marked as `final`
|
||||
- feat: implicit point origins support added
|
||||
- feat: unit default point origin support added
|
||||
- feat: `fma`, `isfinite`, `isinf`, and `isnan` math function added by [@NAThompson](https://github.com/NAThompson)
|
||||
@ -29,10 +30,10 @@
|
||||
- feat: unit text output support added
|
||||
- feat: formatting error messages improved
|
||||
- feat: improve types readability by eliminating extraneous `()` in references, prefixes, and `kind_of`
|
||||
- feat: dimension text output added
|
||||
- feat: dimension and unit text output added
|
||||
- feat: some light and radiation ISQ quantities added
|
||||
- feat: New formatting specification implemented
|
||||
- feat: allow configuring GSL library use
|
||||
- feat: freestanding support added
|
||||
- (!) refactor: `zero_Fahrenheit` renamed to `zeroth_degree_Fahrenheit`
|
||||
- (!) refactor: SI-related trigonometric functions moved to the `si` subnamespace
|
||||
- (!) refactor: `math.h` header file broke up to smaller pieces
|
||||
@ -47,6 +48,9 @@
|
||||
- (!) refactor: `framework.h` introduced
|
||||
- (!) refactor: type list tools made an implementation detail of the library
|
||||
- (!) refactor: header files with the entire system definitions moved up in the directory tree
|
||||
- (!) refactor: `absolute_point_origin` does not use CRTP anymore
|
||||
- refactor: system's units do not inherit from one another anymore
|
||||
- refactor: all units made `final`
|
||||
- refactor: math functions constraints refactored
|
||||
- refactor: `si_quantities.h` added to improve compile-times
|
||||
- refactor: `validate_ascii_string` refactored to `is_basic_literal_character_set`
|
||||
@ -54,6 +58,8 @@
|
||||
- refactor: code refactored to comply with clang-tidy
|
||||
- refactor: remove dependency on `<ranges>` header and switch to use an iterator-based `copy` algorithm
|
||||
- refactor: `terminate` replaced with `abort` and a header file added
|
||||
- refactor: most `std::remove_const_t` removed and some replaced with the GCC-specific workaround
|
||||
- refactor: not needed `remove_reference_t` and `remove_cvref_t` removed
|
||||
- fix: `QuantityLike` conversions required `Q::rep` instead of using one provided by `quantity_like_traits`
|
||||
- fix: `QuantitySpec[Unit]` replaced with `make_reference` in `value_cast`
|
||||
- fix: `ice_point` is now defined with the integral offset from `absolute_zero`
|
||||
@ -82,6 +88,7 @@
|
||||
- docs: "Text Output" chapter updated with the recent formatting changes
|
||||
- docs: formatting grammar language changed to EBNF
|
||||
- docs: "Project structure" chapter expanded
|
||||
- docs: CITATION.cff updated
|
||||
- (!) build: Conan and CMake options refactored
|
||||
- (!) build: `MP_UNITS_AS_SYSTEM_HEADERS` renamed to `MP_UNITS_BUILD_AS_SYSTEM_HEADERS`
|
||||
- (!) build: `MP_UNITS_BUILD_LA` and `MP_UNITS_IWYU` CMake options now have `_DEV_` in the name
|
||||
@ -97,6 +104,7 @@
|
||||
- build(conan): `can_run` check added before running tests
|
||||
- ci: Conan and CMake CI now use different cache names
|
||||
- ci: gcc-14 added
|
||||
- ci: `clang-tidy` CI added
|
||||
|
||||
### 2.1.1 <small>May 16, 2024</small> { id="2.1.1" }
|
||||
|
||||
|
59
conanfile.py
59
conanfile.py
@ -207,12 +207,13 @@ class MPUnitsConan(ConanFile):
|
||||
self.version = version.strip()
|
||||
|
||||
def requirements(self):
|
||||
if self.options.contracts == "gsl-lite":
|
||||
self.requires("gsl-lite/0.41.0")
|
||||
elif self.options.contracts == "ms-gsl":
|
||||
self.requires("ms-gsl/4.0.0")
|
||||
if self._use_fmtlib and not self.options.freestanding:
|
||||
self.requires("fmt/10.2.1")
|
||||
if not self.options.freestanding:
|
||||
if self.options.contracts == "gsl-lite":
|
||||
self.requires("gsl-lite/0.41.0")
|
||||
elif self.options.contracts == "ms-gsl":
|
||||
self.requires("ms-gsl/4.0.0")
|
||||
if self._use_fmtlib:
|
||||
self.requires("fmt/10.2.1")
|
||||
|
||||
def build_requirements(self):
|
||||
if self._build_all:
|
||||
@ -248,9 +249,12 @@ class MPUnitsConan(ConanFile):
|
||||
tc.cache_variables["MP_UNITS_BUILD_CXX_MODULES"] = str(
|
||||
self.options.cxx_modules
|
||||
).upper()
|
||||
tc.cache_variables["MP_UNITS_API_STD_FORMAT"] = str(
|
||||
self.options.std_format
|
||||
).upper()
|
||||
if self.options.freestanding:
|
||||
tc.cache_variables["MP_UNITS_API_FREESTANDING"] = True
|
||||
else:
|
||||
tc.cache_variables["MP_UNITS_API_STD_FORMAT"] = str(
|
||||
self.options.std_format
|
||||
).upper()
|
||||
tc.cache_variables["MP_UNITS_API_STRING_VIEW_RET"] = str(
|
||||
self.options.string_view_ret
|
||||
).upper()
|
||||
@ -258,7 +262,6 @@ class MPUnitsConan(ConanFile):
|
||||
tc.cache_variables["MP_UNITS_API_CONTRACTS"] = str(
|
||||
self.options.contracts
|
||||
).upper()
|
||||
tc.cache_variables["MP_UNITS_API_FREESTANDING"] = self.options.freestanding
|
||||
tc.generate()
|
||||
deps = CMakeDeps(self)
|
||||
deps.generate()
|
||||
@ -285,13 +288,39 @@ class MPUnitsConan(ConanFile):
|
||||
|
||||
def package_info(self):
|
||||
compiler = self.settings.compiler
|
||||
self.cpp_info.components["core"]
|
||||
if self.options.contracts == "gsl-lite":
|
||||
self.cpp_info.components["core"].requires = ["gsl-lite::gsl-lite"]
|
||||
|
||||
# handle contracts
|
||||
if self.options.contracts == "none":
|
||||
self.cpp_info.components["core"].defines.append("MP_UNITS_API_CONTRACTS=0")
|
||||
elif self.options.contracts == "gsl-lite":
|
||||
self.cpp_info.components["core"].requires.append("gsl-lite::gsl-lite")
|
||||
self.cpp_info.components["core"].defines.append("MP_UNITS_API_CONTRACTS=2")
|
||||
elif self.options.contracts == "ms-gsl":
|
||||
self.cpp_info.components["core"].requires = ["ms-gsl::ms-gsl"]
|
||||
if self._use_fmtlib and not self.options.freestanding:
|
||||
self.cpp_info.components["core"].requires.append("ms-gsl::ms-gsl")
|
||||
self.cpp_info.components["core"].defines.append("MP_UNITS_API_CONTRACTS=3")
|
||||
|
||||
# handle API options
|
||||
if self.options.string_view_ret != "auto":
|
||||
self.cpp_info.components["core"].defines.append(
|
||||
"MP_UNITS_API_STRING_VIEW_RET="
|
||||
+ str(int(self.options.string_view_ret == True))
|
||||
)
|
||||
if self.options.no_crtp != "auto":
|
||||
self.cpp_info.components["core"].defines.append(
|
||||
"MP_UNITS_API_NO_CRTP=" + str(int(self.options.no_crtp == True))
|
||||
)
|
||||
if self.options.std_format != "auto":
|
||||
self.cpp_info.components["core"].defines.append(
|
||||
"MP_UNITS_API_STD_FORMAT=" + str(int(self.options.std_format == True))
|
||||
)
|
||||
if self._use_fmtlib:
|
||||
self.cpp_info.components["core"].requires.append("fmt::fmt")
|
||||
|
||||
# handle hosted configuration
|
||||
if not self.options.freestanding:
|
||||
self.cpp_info.components["core"].defines.append("MP_UNITS_HOSTED=1")
|
||||
|
||||
if compiler == "msvc":
|
||||
self.cpp_info.components["core"].cxxflags = ["/utf-8"]
|
||||
|
||||
self.cpp_info.components["systems"].requires = ["core"]
|
||||
|
@ -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>
|
||||
```
|
||||
|
@ -28,32 +28,12 @@ if(${projectPrefix}BUILD_CXX_MODULES)
|
||||
target_compile_features(example_utils INTERFACE cxx_std_20)
|
||||
target_compile_definitions(example_utils INTERFACE ${projectPrefix}MODULES)
|
||||
target_include_directories(example_utils INTERFACE include)
|
||||
target_link_libraries(example_utils INTERFACE mp-units-contracts)
|
||||
endif()
|
||||
|
||||
add_library(example_utils-headers INTERFACE)
|
||||
target_include_directories(example_utils-headers INTERFACE include)
|
||||
|
||||
if(${projectPrefix}API_CONTRACTS STREQUAL "NONE")
|
||||
target_compile_definitions(mp-units-core INTERFACE ${projectPrefix}API_CONTRACTS=0)
|
||||
elseif(${projectPrefix}API_CONTRACTS STREQUAL "GSL-LITE")
|
||||
if(NOT TARGET gsl::gsl-lite)
|
||||
find_package(gsl-lite REQUIRED)
|
||||
endif()
|
||||
if(${projectPrefix}BUILD_CXX_MODULES)
|
||||
target_link_libraries(example_utils INTERFACE gsl::gsl-lite)
|
||||
endif()
|
||||
target_link_libraries(example_utils-headers INTERFACE gsl::gsl-lite)
|
||||
target_compile_definitions(mp-units-core INTERFACE ${projectPrefix}API_CONTRACTS=2)
|
||||
elseif(${projectPrefix}API_CONTRACTS STREQUAL "MS-GSL")
|
||||
if(NOT TARGET Microsoft.GSL::GSL)
|
||||
find_package(Microsoft.GSL REQUIRED)
|
||||
endif()
|
||||
if(${projectPrefix}BUILD_CXX_MODULES)
|
||||
target_link_libraries(example_utils INTERFACE Microsoft.GSL::GSL)
|
||||
endif()
|
||||
target_link_libraries(example_utils-headers INTERFACE Microsoft.GSL::GSL)
|
||||
target_compile_definitions(mp-units-core INTERFACE ${projectPrefix}API_CONTRACTS=3)
|
||||
endif()
|
||||
target_link_libraries(example_utils-headers INTERFACE mp-units-contracts)
|
||||
|
||||
#
|
||||
# add_example(target <depependencies>...)
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
import mp_units;
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <concepts>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
@ -36,14 +36,14 @@ import mp_units.core;
|
||||
using namespace mp_units;
|
||||
|
||||
// clang-format off
|
||||
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 euro : named_unit<"EUR", kind_of<currency>> {} euro;
|
||||
inline constexpr struct us_dollar : named_unit<"USD", kind_of<currency>> {} us_dollar;
|
||||
inline constexpr struct great_british_pound : named_unit<"GBP", kind_of<currency>> {} great_british_pound;
|
||||
inline constexpr struct japanese_jen : named_unit<"JPY", kind_of<currency>> {} japanese_jen;
|
||||
inline constexpr struct euro final : named_unit<"EUR", kind_of<currency>> {} euro;
|
||||
inline constexpr struct us_dollar final : named_unit<"USD", kind_of<currency>> {} us_dollar;
|
||||
inline constexpr struct great_british_pound final : named_unit<"GBP", kind_of<currency>> {} great_british_pound;
|
||||
inline constexpr struct japanese_jen final : named_unit<"JPY", kind_of<currency>> {} japanese_jen;
|
||||
// clang-format on
|
||||
|
||||
namespace unit_symbols {
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "glide_computer_lib.h"
|
||||
#include <mp-units/bits/hacks.h>
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <concepts>
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "glide_computer_lib.h"
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
|
@ -26,6 +26,7 @@
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "ranged_representation.h"
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <compare>
|
||||
#include <limits>
|
||||
#include <numbers>
|
||||
@ -39,7 +40,7 @@ import mp_units;
|
||||
|
||||
namespace geographic {
|
||||
|
||||
inline constexpr struct mean_sea_level : mp_units::absolute_point_origin<mean_sea_level, mp_units::isq::altitude> {
|
||||
inline constexpr struct mean_sea_level final : mp_units::absolute_point_origin<mp_units::isq::altitude> {
|
||||
} mean_sea_level;
|
||||
|
||||
using msl_altitude = mp_units::quantity_point<mp_units::isq::altitude[mp_units::si::metre], mean_sea_level>;
|
||||
@ -67,10 +68,9 @@ struct MP_UNITS_STD_FMT::formatter<geographic::msl_altitude, Char> :
|
||||
|
||||
namespace geographic {
|
||||
|
||||
inline constexpr struct equator : mp_units::absolute_point_origin<equator, mp_units::isq::angular_measure> {
|
||||
inline constexpr struct equator final : mp_units::absolute_point_origin<mp_units::isq::angular_measure> {
|
||||
} equator;
|
||||
inline constexpr struct prime_meridian :
|
||||
mp_units::absolute_point_origin<prime_meridian, mp_units::isq::angular_measure> {
|
||||
inline constexpr struct prime_meridian final : mp_units::absolute_point_origin<mp_units::isq::angular_measure> {
|
||||
} prime_meridian;
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "validated_type.h"
|
||||
#include <mp-units/bits/hacks.h>
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <algorithm>
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include <mp-units/bits/hacks.h>
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/contracts.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <compare> // IWYU pragma: export
|
||||
#include <ostream>
|
||||
#include <utility>
|
||||
|
@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <algorithm>
|
||||
#include <locale>
|
||||
#include <tuple>
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "kalman.h"
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "kalman.h"
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "kalman.h"
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "kalman.h"
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "kalman.h"
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "kalman.h"
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
@ -63,7 +64,7 @@ int main()
|
||||
|
||||
const quantity process_noise_variance = 0.0001 * pow<2>(deg_C);
|
||||
const estimate initial{state{qp{60. * deg_C}}, 100. * deg_C};
|
||||
const std::array measurements = {qp{49.986 * deg_C}, qp{49.963 * deg_C}, qp{50.09 * deg_C}, qp{50.001 * deg_C},
|
||||
const std::array measurements = {qp{49.986 * deg_C}, qp{49.963 * deg_C}, qp{50.097 * deg_C}, qp{50.001 * deg_C},
|
||||
qp{50.018 * deg_C}, qp{50.05 * deg_C}, qp{49.938 * deg_C}, qp{49.858 * deg_C},
|
||||
qp{49.965 * deg_C}, qp{50.114 * deg_C}};
|
||||
const quantity measurement_error = 0.1 * deg_C;
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "kalman.h"
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "kalman.h"
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -26,6 +26,7 @@
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <iostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
import mp_units;
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -21,6 +21,7 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "geographic.h"
|
||||
#include "ranged_representation.h"
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
@ -30,6 +31,7 @@
|
||||
#ifdef MP_UNITS_MODULES
|
||||
import mp_units;
|
||||
#else
|
||||
#include <mp-units/bits/fmt.h>
|
||||
#include <mp-units/systems/international.h>
|
||||
#include <mp-units/systems/isq/space_and_time.h>
|
||||
#include <mp-units/systems/si.h>
|
||||
@ -43,7 +45,7 @@ using namespace geographic;
|
||||
enum class earth_gravity_model : std::int8_t { egm84_15, egm95_5, egm2008_1 };
|
||||
|
||||
template<earth_gravity_model M>
|
||||
struct height_above_ellipsoid_t : absolute_point_origin<height_above_ellipsoid_t<M>, isq::altitude> {
|
||||
struct height_above_ellipsoid_t final : absolute_point_origin<isq::altitude> {
|
||||
static constexpr earth_gravity_model egm = M;
|
||||
};
|
||||
template<earth_gravity_model M>
|
||||
@ -113,7 +115,7 @@ hae_altitude<M> to_hae(msl_altitude msl, position<long double> pos)
|
||||
// **** HAL ****
|
||||
|
||||
// clang-format off
|
||||
inline constexpr struct height_above_launch : absolute_point_origin<height_above_launch, isq::altitude> {} height_above_launch;
|
||||
inline constexpr struct height_above_launch final : absolute_point_origin<isq::altitude> {} height_above_launch;
|
||||
// clang-format on
|
||||
|
||||
using hal_altitude = quantity_point<isq::altitude[si::metre], height_above_launch>;
|
||||
|
@ -83,26 +83,29 @@ check_cxx_feature_supported(__cpp_lib_format ${projectPrefix}LIB_FORMAT_SUPPORTE
|
||||
check_cxx_feature_supported("__cpp_constexpr >= 202211L" ${projectPrefix}STATIC_CONSTEXPR_VARS_IN_CONSTEXPR_FUNCTIONS)
|
||||
check_cxx_feature_supported(__cpp_explicit_this_parameter ${projectPrefix}EXPLICIT_THIS_PARAMETER_SUPPORTED)
|
||||
|
||||
# libc++ has a basic supports for std::format but does not set __cpp_lib_format
|
||||
# https://github.com/llvm/llvm-project/issues/77773
|
||||
if(NOT ${projectPrefix}LIB_FORMAT_SUPPORTED
|
||||
AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
|
||||
AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "17"
|
||||
AND ${projectPrefix}LIBCXX
|
||||
)
|
||||
message(STATUS "Clang 17+ with libc++ detected, overriding `std::format` support")
|
||||
set(${projectPrefix}LIB_FORMAT_SUPPORTED 1)
|
||||
endif()
|
||||
|
||||
# validate settings
|
||||
if(NOT ${projectPrefix}API_FREESTANDING
|
||||
AND ${projectPrefix}API_STD_FORMAT STREQUAL "TRUE"
|
||||
AND NOT
|
||||
(${projectPrefix}LIB_FORMAT_SUPPORTED
|
||||
# libc++ has a basic supports for std::format but does not set __cpp_lib_format
|
||||
# https://github.com/llvm/llvm-project/issues/77773
|
||||
OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "17"
|
||||
AND ${projectPrefix}LIBCXX))
|
||||
if(NOT ${projectPrefix}API_FREESTANDING AND "${projectPrefix}API_STD_FORMAT" AND NOT
|
||||
${projectPrefix}LIB_FORMAT_SUPPORTED
|
||||
)
|
||||
message(FATAL_ERROR "`std::format` enabled but not supported")
|
||||
endif()
|
||||
|
||||
if(${projectPrefix}API_STRING_VIEW_RET STREQUAL "TRUE" AND NOT
|
||||
${projectPrefix}STATIC_CONSTEXPR_VARS_IN_CONSTEXPR_FUNCTIONS
|
||||
)
|
||||
if("${projectPrefix}API_STRING_VIEW_RET" AND NOT ${projectPrefix}STATIC_CONSTEXPR_VARS_IN_CONSTEXPR_FUNCTIONS)
|
||||
message(FATAL_ERROR "`std::string_view` returns enabled but not supported")
|
||||
endif()
|
||||
|
||||
if(${projectPrefix}API_NO_CRTP STREQUAL "TRUE" AND NOT ${projectPrefix}EXPLICIT_THIS_PARAMETER_SUPPORTED)
|
||||
if("${projectPrefix}API_NO_CRTP" AND NOT ${projectPrefix}EXPLICIT_THIS_PARAMETER_SUPPORTED)
|
||||
message(FATAL_ERROR "`NO_CRTP` mode enabled but explicit `this` parameter is not supported")
|
||||
endif()
|
||||
|
||||
@ -116,6 +119,7 @@ else()
|
||||
endif()
|
||||
|
||||
# components/modules
|
||||
include(MPUnitsContracts)
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(systems)
|
||||
|
||||
|
41
src/cmake/MPUnitsContracts.cmake
Normal file
41
src/cmake/MPUnitsContracts.cmake
Normal file
@ -0,0 +1,41 @@
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2018 Mateusz Pusz
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
add_library(mp-units-contracts INTERFACE)
|
||||
|
||||
if(${projectPrefix}API_CONTRACTS STREQUAL "NONE")
|
||||
target_compile_definitions(mp-units-contracts INTERFACE ${projectPrefix}API_CONTRACTS=0)
|
||||
elseif(${projectPrefix}API_CONTRACTS STREQUAL "GSL-LITE")
|
||||
if(NOT TARGET gsl::gsl-lite)
|
||||
find_package(gsl-lite REQUIRED)
|
||||
endif()
|
||||
target_link_libraries(mp-units-contracts INTERFACE gsl::gsl-lite)
|
||||
target_compile_definitions(mp-units-contracts INTERFACE ${projectPrefix}API_CONTRACTS=2)
|
||||
elseif(${projectPrefix}API_CONTRACTS STREQUAL "MS-GSL")
|
||||
if(NOT TARGET Microsoft.GSL::GSL)
|
||||
find_package(Microsoft.GSL REQUIRED)
|
||||
endif()
|
||||
target_link_libraries(mp-units-contracts INTERFACE Microsoft.GSL::GSL)
|
||||
target_compile_definitions(mp-units-contracts INTERFACE ${projectPrefix}API_CONTRACTS=3)
|
||||
endif()
|
||||
|
||||
install(TARGETS mp-units-contracts EXPORT mp-unitsTargets)
|
@ -23,8 +23,7 @@
|
||||
cmake_minimum_required(VERSION 3.23)
|
||||
|
||||
function(set_feature_flag name)
|
||||
set(val_list "TRUE" "FALSE")
|
||||
if(${projectPrefix}${name} IN_LIST val_list)
|
||||
if(NOT ${projectPrefix}${name} STREQUAL "AUTO")
|
||||
target_compile_definitions(
|
||||
mp-units-core ${${projectPrefix}TARGET_SCOPE} ${projectPrefix}${name}=$<BOOL:${${projectPrefix}${name}}>
|
||||
)
|
||||
@ -36,15 +35,16 @@ add_mp_units_module(
|
||||
core mp-units-core
|
||||
HEADERS include/mp-units/bits/core_gmf.h
|
||||
include/mp-units/bits/get_associated_quantity.h
|
||||
include/mp-units/bits/get_common_base.h
|
||||
include/mp-units/bits/hacks.h
|
||||
include/mp-units/bits/math_concepts.h
|
||||
include/mp-units/bits/module_macros.h
|
||||
include/mp-units/bits/quantity_spec_hierarchy.h
|
||||
include/mp-units/bits/ratio.h
|
||||
include/mp-units/bits/sudo_cast.h
|
||||
include/mp-units/bits/text_tools.h
|
||||
include/mp-units/bits/type_list.h
|
||||
include/mp-units/ext/algorithm.h
|
||||
include/mp-units/ext/contracts.h
|
||||
include/mp-units/ext/fixed_string.h
|
||||
include/mp-units/ext/prime.h
|
||||
include/mp-units/ext/type_name.h
|
||||
@ -86,6 +86,7 @@ if(NOT ${projectPrefix}API_FREESTANDING)
|
||||
FILES
|
||||
include/mp-units/bits/fmt.h
|
||||
include/mp-units/bits/requires_hosted.h
|
||||
include/mp-units/ext/format.h
|
||||
include/mp-units/math.h
|
||||
include/mp-units/ostream.h
|
||||
include/mp-units/format.h
|
||||
@ -99,8 +100,8 @@ set_feature_flag(API_NO_CRTP)
|
||||
|
||||
# Text formatting
|
||||
if(NOT ${projectPrefix}API_FREESTANDING
|
||||
AND (${projectPrefix}API_STD_FORMAT STREQUAL "FALSE" OR (${projectPrefix}API_STD_FORMAT STREQUAL "AUTO"
|
||||
AND NOT ${projectPrefix}LIB_FORMAT_SUPPORTED))
|
||||
AND (NOT ${projectPrefix}API_STD_FORMAT OR (${projectPrefix}API_STD_FORMAT STREQUAL "AUTO"
|
||||
AND NOT ${projectPrefix}LIB_FORMAT_SUPPORTED))
|
||||
)
|
||||
if(NOT TARGET fmt::fmt)
|
||||
find_package(fmt REQUIRED)
|
||||
@ -109,21 +110,7 @@ if(NOT ${projectPrefix}API_FREESTANDING
|
||||
endif()
|
||||
|
||||
# Contracts checking
|
||||
if(${projectPrefix}API_CONTRACTS STREQUAL "NONE")
|
||||
target_compile_definitions(mp-units-core ${${projectPrefix}TARGET_SCOPE} ${projectPrefix}API_CONTRACTS=0)
|
||||
elseif(${projectPrefix}API_CONTRACTS STREQUAL "GSL-LITE")
|
||||
if(NOT TARGET gsl::gsl-lite)
|
||||
find_package(gsl-lite REQUIRED)
|
||||
endif()
|
||||
target_link_libraries(mp-units-core ${${projectPrefix}TARGET_SCOPE} gsl::gsl-lite)
|
||||
target_compile_definitions(mp-units-core ${${projectPrefix}TARGET_SCOPE} ${projectPrefix}API_CONTRACTS=2)
|
||||
elseif(${projectPrefix}API_CONTRACTS STREQUAL "MS-GSL")
|
||||
if(NOT TARGET Microsoft.GSL::GSL)
|
||||
find_package(Microsoft.GSL REQUIRED)
|
||||
endif()
|
||||
target_link_libraries(mp-units-core ${${projectPrefix}TARGET_SCOPE} Microsoft.GSL::GSL)
|
||||
target_compile_definitions(mp-units-core ${${projectPrefix}TARGET_SCOPE} ${projectPrefix}API_CONTRACTS=3)
|
||||
endif()
|
||||
target_link_libraries(mp-units-core ${${projectPrefix}TARGET_SCOPE} mp-units-contracts)
|
||||
|
||||
# C++20 modules
|
||||
if(${projectPrefix}BUILD_CXX_MODULES)
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <mp-units/bits/hacks.h>
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/contracts.h>
|
||||
#include <array>
|
||||
#include <compare>
|
||||
#include <concepts>
|
||||
@ -44,23 +45,13 @@
|
||||
#include <utility>
|
||||
|
||||
#if MP_UNITS_HOSTED
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <cmath>
|
||||
#include <locale>
|
||||
#include <ostream>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#if MP_UNITS_USE_FMTLIB
|
||||
MP_UNITS_DIAGNOSTIC_PUSH
|
||||
MP_UNITS_DIAGNOSTIC_IGNORE_UNREACHABLE
|
||||
MP_UNITS_DIAGNOSTIC_IGNORE_SHADOW
|
||||
#include <fmt/format.h>
|
||||
MP_UNITS_DIAGNOSTIC_POP
|
||||
#else
|
||||
#include <format>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if __cpp_lib_text_encoding
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include <mp-units/ext/algorithm.h>
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
#include <mp-units/ext/contracts.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <array>
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
|
@ -56,7 +56,7 @@ template<QuantitySpec A, QuantitySpec B>
|
||||
}
|
||||
|
||||
template<QuantitySpec A, QuantitySpec B>
|
||||
[[nodiscard]] consteval auto have_common_base(A a, B b)
|
||||
[[nodiscard]] consteval bool have_common_base(A a, B b)
|
||||
{
|
||||
constexpr std::size_t a_length = hierarchy_path_length(A{});
|
||||
constexpr std::size_t b_length = hierarchy_path_length(B{});
|
||||
@ -68,7 +68,7 @@ template<QuantitySpec A, QuantitySpec B>
|
||||
|
||||
template<QuantitySpec A, QuantitySpec B>
|
||||
requires(have_common_base_in_hierarchy_of_equal_length(A{}, B{}))
|
||||
[[nodiscard]] consteval auto get_common_base_for_hierarchy_of_equal_length(A a, B b)
|
||||
[[nodiscard]] consteval QuantitySpec auto get_common_base_for_hierarchy_of_equal_length(A a, B b)
|
||||
{
|
||||
if constexpr (is_same_v<A, B>)
|
||||
return a;
|
||||
@ -78,14 +78,29 @@ template<QuantitySpec A, QuantitySpec B>
|
||||
|
||||
template<QuantitySpec A, QuantitySpec B>
|
||||
requires(have_common_base(A{}, B{}))
|
||||
[[nodiscard]] consteval auto get_common_base(A a, B b)
|
||||
[[nodiscard]] consteval QuantitySpec auto get_common_base(A a, B b)
|
||||
{
|
||||
constexpr int a_length = hierarchy_path_length(A{});
|
||||
constexpr int b_length = hierarchy_path_length(B{});
|
||||
constexpr std::size_t a_length = hierarchy_path_length(A{});
|
||||
constexpr std::size_t b_length = hierarchy_path_length(B{});
|
||||
if constexpr (a_length > b_length)
|
||||
return get_common_base_for_hierarchy_of_equal_length(hierarchy_path_advance<a_length - b_length>(a), b);
|
||||
else
|
||||
return get_common_base_for_hierarchy_of_equal_length(a, hierarchy_path_advance<b_length - a_length>(b));
|
||||
}
|
||||
|
||||
template<QuantitySpec Child, QuantitySpec Parent>
|
||||
[[nodiscard]] consteval bool is_child_of(Child ch, Parent p)
|
||||
{
|
||||
if constexpr (Child{} == Parent{})
|
||||
return std::true_type{};
|
||||
else {
|
||||
constexpr std::size_t child_length = hierarchy_path_length(Child{});
|
||||
constexpr std::size_t parent_length = hierarchy_path_length(Parent{});
|
||||
if constexpr (parent_length > child_length)
|
||||
return false;
|
||||
else
|
||||
return hierarchy_path_advance<child_length - parent_length>(ch) == p;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mp_units::detail
|
@ -27,6 +27,7 @@
|
||||
#include <mp-units/compat_macros.h>
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
#include <mp-units/ext/contracts.h>
|
||||
#include <compare> // IWYU pragma: export
|
||||
#include <cstdint>
|
||||
#include <numeric>
|
||||
|
@ -28,14 +28,14 @@
|
||||
|
||||
#ifdef MP_UNITS_API_NO_CRTP
|
||||
|
||||
#define QUANTITY_SPEC(name, ...) \
|
||||
inline constexpr struct name : ::mp_units::quantity_spec<__VA_ARGS__> { \
|
||||
#define QUANTITY_SPEC(name, ...) \
|
||||
inline constexpr struct name final : ::mp_units::quantity_spec<__VA_ARGS__> { \
|
||||
} name
|
||||
|
||||
#else
|
||||
|
||||
#define QUANTITY_SPEC(name, ...) \
|
||||
inline constexpr struct name : ::mp_units::quantity_spec<name, __VA_ARGS__> { \
|
||||
#define QUANTITY_SPEC(name, ...) \
|
||||
inline constexpr struct name final : ::mp_units::quantity_spec<name, __VA_ARGS__> { \
|
||||
} name
|
||||
|
||||
#endif
|
||||
@ -83,26 +83,12 @@
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
|
||||
// IWYU pragma: begin_exports
|
||||
#if MP_UNITS_USE_FMTLIB
|
||||
MP_UNITS_DIAGNOSTIC_PUSH
|
||||
MP_UNITS_DIAGNOSTIC_IGNORE_UNREACHABLE
|
||||
MP_UNITS_DIAGNOSTIC_IGNORE_SHADOW
|
||||
#include <fmt/format.h>
|
||||
MP_UNITS_DIAGNOSTIC_POP
|
||||
#else
|
||||
#include <format>
|
||||
#endif
|
||||
// IWYU pragma: end_exports
|
||||
|
||||
#endif
|
||||
|
||||
#endif // MP_UNITS_HOSTED
|
||||
|
||||
#if MP_UNITS_API_CONTRACTS == 2 || __has_include(<gsl/gsl-lite.hpp>)
|
||||
|
||||
#include <gsl/gsl-lite.hpp>
|
||||
|
||||
#define MP_UNITS_EXPECTS(expr) gsl_Expects(expr)
|
||||
#define MP_UNITS_EXPECTS_DEBUG(expr) gsl_ExpectsDebug(expr)
|
||||
#define MP_UNITS_ASSERT(expr) gsl_Assert(expr)
|
||||
@ -110,9 +96,6 @@ MP_UNITS_DIAGNOSTIC_POP
|
||||
|
||||
#elif MP_UNITS_API_CONTRACTS == 3 || __has_include(<gsl/gsl>)
|
||||
|
||||
#include <gsl/gsl>
|
||||
#include <cassert>
|
||||
|
||||
#define MP_UNITS_EXPECTS(expr) Expects(expr)
|
||||
#if defined NDEBUG
|
||||
#define MP_UNITS_EXPECTS_DEBUG(expr) static_cast<void>(0)
|
||||
|
49
src/core/include/mp-units/ext/contracts.h
Normal file
49
src/core/include/mp-units/ext/contracts.h
Normal file
@ -0,0 +1,49 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
|
||||
#include <mp-units/bits/hacks.h>
|
||||
#include <mp-units/compat_macros.h>
|
||||
|
||||
#if MP_UNITS_API_CONTRACTS == 2 || __has_include(<gsl/gsl-lite.hpp>)
|
||||
|
||||
#if MP_UNITS_HOSTED
|
||||
#include <gsl/gsl-lite.hpp>
|
||||
#else
|
||||
#include <mp-units/bits/requires_hosted.h>
|
||||
#endif
|
||||
|
||||
#elif MP_UNITS_API_CONTRACTS == 3 || __has_include(<gsl/gsl>)
|
||||
|
||||
#if MP_UNITS_HOSTED
|
||||
#include <gsl/gsl>
|
||||
#include <cassert>
|
||||
#else
|
||||
#include <mp-units/bits/requires_hosted.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // MP_UNITS_IN_MODULE_INTERFACE
|
@ -32,12 +32,14 @@
|
||||
#include <mp-units/ext/type_traits.h>
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
#include <mp-units/ext/contracts.h>
|
||||
#include <compare> // IWYU pragma: export
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <ranges>
|
||||
#include <string_view>
|
||||
#if MP_UNITS_HOSTED
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <ostream>
|
||||
#endif
|
||||
#endif
|
||||
|
42
src/core/include/mp-units/ext/format.h
Normal file
42
src/core/include/mp-units/ext/format.h
Normal file
@ -0,0 +1,42 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
|
||||
#include <mp-units/bits/requires_hosted.h>
|
||||
//
|
||||
#include <mp-units/bits/hacks.h>
|
||||
#include <mp-units/compat_macros.h>
|
||||
|
||||
#if MP_UNITS_USE_FMTLIB
|
||||
MP_UNITS_DIAGNOSTIC_PUSH
|
||||
MP_UNITS_DIAGNOSTIC_IGNORE_UNREACHABLE
|
||||
MP_UNITS_DIAGNOSTIC_IGNORE_SHADOW
|
||||
#include <fmt/format.h>
|
||||
MP_UNITS_DIAGNOSTIC_POP
|
||||
#else
|
||||
#include <format>
|
||||
#endif
|
||||
|
||||
#endif
|
@ -34,6 +34,7 @@
|
||||
#include <mp-units/framework/symbol_text.h>
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
#include <mp-units/ext/contracts.h>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
@ -61,9 +62,9 @@ namespace mp_units {
|
||||
* For example:
|
||||
*
|
||||
* @code{.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_mass : base_dimension<"M"> {} dim_mass;
|
||||
* inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length;
|
||||
* inline constexpr struct dim_time final : base_dimension<"T"> {} dim_time;
|
||||
* inline constexpr struct dim_mass final : base_dimension<"M"> {} dim_mass;
|
||||
* @endcode
|
||||
*
|
||||
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
||||
@ -86,6 +87,9 @@ struct base_dimension_less : std::bool_constant<(Lhs::symbol < Rhs::symbol)> {};
|
||||
template<typename T1, typename T2>
|
||||
using type_list_of_base_dimension_less = expr_less<T1, T2, base_dimension_less>;
|
||||
|
||||
template<detail::DerivedDimensionExpr... Expr>
|
||||
struct derived_dimension_impl : detail::expr_fractions<detail::is_dimension_one, Expr...> {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
@ -131,7 +135,7 @@ using type_list_of_base_dimension_less = expr_less<T1, T2, base_dimension_less>;
|
||||
* instantiate this type automatically based on the dimensional arithmetic equation provided by the user.
|
||||
*/
|
||||
template<detail::DerivedDimensionExpr... Expr>
|
||||
struct derived_dimension : detail::expr_fractions<detail::is_dimension_one, Expr...> {};
|
||||
struct derived_dimension final : detail::derived_dimension_impl<Expr...> {};
|
||||
|
||||
/**
|
||||
* @brief Dimension one
|
||||
@ -140,7 +144,7 @@ struct derived_dimension : detail::expr_fractions<detail::is_dimension_one, Expr
|
||||
* dimensions are zero. It is a dimension of a quantity of dimension one also known as
|
||||
* "dimensionless".
|
||||
*/
|
||||
MP_UNITS_EXPORT inline constexpr struct dimension_one : derived_dimension<> {
|
||||
MP_UNITS_EXPORT inline constexpr struct dimension_one final : detail::derived_dimension_impl<> {
|
||||
} dimension_one;
|
||||
|
||||
namespace detail {
|
||||
@ -279,13 +283,13 @@ constexpr Out dimension_symbol_impl(Out out, const type_list<Nums...>& nums, con
|
||||
}
|
||||
|
||||
template<typename CharT, std::output_iterator<CharT> Out, typename... Expr>
|
||||
constexpr Out dimension_symbol_impl(Out out, const derived_dimension<Expr...>&, const dimension_symbol_formatting& fmt,
|
||||
bool negative_power)
|
||||
constexpr Out dimension_symbol_impl(Out out, const derived_dimension_impl<Expr...>&,
|
||||
const dimension_symbol_formatting& fmt, bool negative_power)
|
||||
{
|
||||
(void)negative_power;
|
||||
MP_UNITS_EXPECTS(negative_power == false);
|
||||
return dimension_symbol_impl<CharT>(out, typename derived_dimension<Expr...>::_num_{},
|
||||
typename derived_dimension<Expr...>::_den_{}, fmt);
|
||||
return dimension_symbol_impl<CharT>(out, typename derived_dimension_impl<Expr...>::_num_{},
|
||||
typename derived_dimension_impl<Expr...>::_den_{}, fmt);
|
||||
}
|
||||
|
||||
|
||||
|
@ -42,20 +42,13 @@ template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_base_dimension =
|
||||
requires(T* t) { to_base_specialization_of_base_dimension(t); };
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_base_dimension = false;
|
||||
|
||||
template<symbol_text Symbol>
|
||||
inline constexpr bool is_specialization_of_base_dimension<base_dimension<Symbol>> = true;
|
||||
|
||||
/**
|
||||
* @brief A concept matching all named base dimensions in the library.
|
||||
*
|
||||
* Satisfied by all dimension types derived from a specialization of `base_dimension`.
|
||||
*/
|
||||
template<typename T>
|
||||
concept BaseDimension =
|
||||
is_derived_from_specialization_of_base_dimension<T> && (!is_specialization_of_base_dimension<T>);
|
||||
concept BaseDimension = is_derived_from_specialization_of_base_dimension<T> && std::is_final_v<T>;
|
||||
|
||||
template<typename T>
|
||||
struct is_dimension_one : std::false_type {};
|
||||
@ -91,7 +84,8 @@ namespace detail {
|
||||
* being the `dimension_one`.
|
||||
*/
|
||||
template<typename T>
|
||||
concept DerivedDimension = is_specialization_of<T, derived_dimension> || is_dimension_one<T>::value;
|
||||
concept DerivedDimension =
|
||||
(is_specialization_of<T, derived_dimension> || is_dimension_one<T>::value) && std::is_final_v<T>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
namespace mp_units {
|
||||
|
@ -517,8 +517,7 @@ template<typename T, auto... Ms>
|
||||
constexpr T get_value(const magnitude<Ms...>&)
|
||||
{
|
||||
// Force the expression to be evaluated in a constexpr context, to catch, e.g., overflow.
|
||||
constexpr auto result = detail::checked_static_cast<T>((detail::compute_base_power<T>(Ms) * ... * T{1}));
|
||||
|
||||
constexpr T result = detail::checked_static_cast<T>((detail::compute_base_power<T>(Ms) * ... * T{1}));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -677,16 +676,6 @@ template<auto... Ms>
|
||||
|
||||
[[nodiscard]] consteval auto denominator(Magnitude auto m) { return numerator(pow<-1>(m)); }
|
||||
|
||||
// TODO This probably should not be exported but is used in chrono.h
|
||||
MP_UNITS_EXPORT constexpr ratio as_ratio(Magnitude auto m)
|
||||
requires(is_rational(decltype(m){}))
|
||||
{
|
||||
return ratio{
|
||||
get_value<std::intmax_t>(numerator(m)),
|
||||
get_value<std::intmax_t>(denominator(m)),
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Common Magnitude.
|
||||
//
|
||||
@ -758,7 +747,7 @@ template<auto H1, auto... T1, auto H2, auto... T2>
|
||||
template<auto... Ms>
|
||||
[[nodiscard]] consteval auto common_magnitude_type_impl(magnitude<Ms...>)
|
||||
{
|
||||
return (decltype(get_base_value(Ms)){} * ... * std::intmax_t{});
|
||||
return (std::intmax_t{} * ... * decltype(get_base_value(Ms)){});
|
||||
}
|
||||
|
||||
// Returns the most precise type to express the magnitude factor
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <mp-units/framework/unit_concepts.h>
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
#include <mp-units/ext/contracts.h>
|
||||
#include <compare> // IWYU pragma: export
|
||||
#include <utility>
|
||||
#endif
|
||||
@ -45,16 +46,21 @@ namespace mp_units {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<auto UFrom, auto UTo>
|
||||
concept IntegralConversionFactor = Unit<decltype(UFrom)> && Unit<decltype(UTo)> &&
|
||||
is_integral(get_canonical_unit(UFrom).mag / get_canonical_unit(UTo).mag);
|
||||
template<Unit UFrom, Unit UTo>
|
||||
[[nodiscard]] consteval bool integral_conversion_factor(UFrom from, UTo to)
|
||||
{
|
||||
if constexpr (is_same_v<UFrom, UTo>)
|
||||
return true;
|
||||
else
|
||||
return is_integral(get_canonical_unit(from).mag / get_canonical_unit(to).mag);
|
||||
}
|
||||
|
||||
template<typename QFrom, typename QTo>
|
||||
concept QuantityConvertibleTo =
|
||||
Quantity<QFrom> && Quantity<QTo> && implicitly_convertible(QFrom::quantity_spec, QTo::quantity_spec) &&
|
||||
convertible(QFrom::unit, QTo::unit) &&
|
||||
(treat_as_floating_point<typename QTo::rep> ||
|
||||
(!treat_as_floating_point<typename QFrom::rep> && IntegralConversionFactor<QFrom::unit, QTo::unit>)) &&
|
||||
(!treat_as_floating_point<typename QFrom::rep> && (integral_conversion_factor(QFrom::unit, QTo::unit)))) &&
|
||||
// TODO consider providing constraints of sudo_cast here rather than testing if it can be called (its return type is
|
||||
// deduced thus the function is evaluated here and may emit truncating conversion or other warnings)
|
||||
requires(QFrom q) { detail::sudo_cast<QTo>(q); };
|
||||
|
@ -35,11 +35,10 @@
|
||||
|
||||
namespace mp_units {
|
||||
|
||||
MP_UNITS_EXPORT template<typename Derived, QuantitySpec auto QS>
|
||||
MP_UNITS_EXPORT template<QuantitySpec auto QS>
|
||||
// NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)
|
||||
struct absolute_point_origin {
|
||||
static constexpr QuantitySpec auto quantity_spec = QS;
|
||||
using _type_ = absolute_point_origin;
|
||||
};
|
||||
|
||||
MP_UNITS_EXPORT template<QuantityPoint auto QP>
|
||||
@ -56,7 +55,7 @@ struct relative_point_origin {
|
||||
};
|
||||
|
||||
template<QuantitySpec auto QS>
|
||||
struct zeroth_point_origin_ : absolute_point_origin<zeroth_point_origin_<QS>, QS> {};
|
||||
struct zeroth_point_origin_ final : absolute_point_origin<QS> {};
|
||||
|
||||
MP_UNITS_EXPORT template<QuantitySpec auto QS>
|
||||
inline constexpr zeroth_point_origin_<QS> zeroth_point_origin;
|
||||
@ -81,9 +80,8 @@ MP_UNITS_EXPORT template<PointOrigin PO1, PointOrigin PO2>
|
||||
[[nodiscard]] consteval bool operator==(PO1 po1, PO2 po2)
|
||||
{
|
||||
if constexpr (detail::AbsolutePointOrigin<PO1> && detail::AbsolutePointOrigin<PO2>)
|
||||
return is_same_v<typename PO1::_type_, typename PO2::_type_> ||
|
||||
(detail::is_zeroth_point_origin(po1) && detail::is_zeroth_point_origin(po2) &&
|
||||
interconvertible(po1.quantity_spec, po2.quantity_spec));
|
||||
return is_same_v<PO1, PO2> || (detail::is_zeroth_point_origin(po1) && detail::is_zeroth_point_origin(po2) &&
|
||||
interconvertible(po1.quantity_spec, po2.quantity_spec));
|
||||
else if constexpr (detail::RelativePointOrigin<PO1> && detail::RelativePointOrigin<PO2>)
|
||||
return PO1::quantity_point == PO2::quantity_point;
|
||||
else if constexpr (detail::RelativePointOrigin<PO1>)
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
namespace mp_units {
|
||||
|
||||
MP_UNITS_EXPORT template<typename Derived, QuantitySpec auto QS>
|
||||
MP_UNITS_EXPORT template<QuantitySpec auto QS>
|
||||
struct absolute_point_origin;
|
||||
|
||||
namespace detail {
|
||||
@ -40,22 +40,15 @@ namespace detail {
|
||||
template<typename T>
|
||||
inline constexpr bool is_quantity_point = false;
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_absolute_point_origin = false;
|
||||
|
||||
template<typename D, auto Q>
|
||||
inline constexpr bool is_specialization_of_absolute_point_origin<absolute_point_origin<D, Q>> = true;
|
||||
|
||||
template<typename D, auto Q>
|
||||
void to_base_specialization_of_absolute_point_origin(const volatile absolute_point_origin<D, Q>*);
|
||||
template<auto Q>
|
||||
void to_base_specialization_of_absolute_point_origin(const volatile absolute_point_origin<Q>*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_absolute_point_origin =
|
||||
requires(T* t) { to_base_specialization_of_absolute_point_origin(t); };
|
||||
|
||||
template<typename T>
|
||||
concept AbsolutePointOrigin =
|
||||
is_derived_from_specialization_of_absolute_point_origin<T> && !is_specialization_of_absolute_point_origin<T>;
|
||||
concept AbsolutePointOrigin = is_derived_from_specialization_of_absolute_point_origin<T> && std::is_final_v<T>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@ -72,12 +65,6 @@ struct relative_point_origin;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_relative_point_origin = false;
|
||||
|
||||
template<auto QP>
|
||||
inline constexpr bool is_specialization_of_relative_point_origin<relative_point_origin<QP>> = true;
|
||||
|
||||
template<auto QP>
|
||||
void to_base_specialization_of_relative_point_origin(const volatile relative_point_origin<QP>*);
|
||||
|
||||
@ -86,8 +73,7 @@ inline constexpr bool is_derived_from_specialization_of_relative_point_origin =
|
||||
requires(T* t) { to_base_specialization_of_relative_point_origin(t); };
|
||||
|
||||
template<typename T>
|
||||
concept RelativePointOrigin =
|
||||
is_derived_from_specialization_of_relative_point_origin<T> && !is_specialization_of_relative_point_origin<T>;
|
||||
concept RelativePointOrigin = is_derived_from_specialization_of_relative_point_origin<T> && std::is_final_v<T>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
@ -23,9 +23,9 @@
|
||||
#pragma once
|
||||
|
||||
// IWYU pragma: private, include <mp-units/framework.h>
|
||||
#include <mp-units/bits/get_common_base.h>
|
||||
#include <mp-units/bits/hacks.h>
|
||||
#include <mp-units/bits/module_macros.h>
|
||||
#include <mp-units/bits/quantity_spec_hierarchy.h>
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/algorithm.h>
|
||||
#include <mp-units/ext/type_name.h>
|
||||
@ -199,13 +199,13 @@ MP_UNITS_EXPORT_END
|
||||
* For example:
|
||||
*
|
||||
* @code{.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_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 length : quantity_spec<dim_length> {} length;
|
||||
* inline constexpr struct mass : quantity_spec<dim_mass> {} mass;
|
||||
* inline constexpr struct time : quantity_spec<dim_time> {} time;
|
||||
* inline constexpr struct length final : quantity_spec<dim_length> {} length;
|
||||
* inline constexpr struct mass final : quantity_spec<dim_mass> {} mass;
|
||||
* inline constexpr struct time final : quantity_spec<dim_time> {} time;
|
||||
* @endcode
|
||||
*
|
||||
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
||||
@ -225,6 +225,7 @@ template<typename Self, detail::BaseDimension auto Dim, one_of<quantity_characte
|
||||
requires(... && !QuantitySpec<decltype(Args)>)
|
||||
struct quantity_spec<Self, Dim, Args...> : detail::quantity_spec_interface<Self> {
|
||||
#endif
|
||||
using _base_type_ = quantity_spec;
|
||||
static constexpr detail::BaseDimension auto dimension = Dim;
|
||||
static constexpr quantity_character character = detail::quantity_character_init<Args...>(quantity_character::scalar);
|
||||
};
|
||||
@ -243,12 +244,12 @@ struct quantity_spec<Self, Dim, Args...> : detail::quantity_spec_interface<Self>
|
||||
* For example:
|
||||
*
|
||||
* @code{.cpp}
|
||||
* inline constexpr struct area : quantity_spec<pow<2>(length)> {} area;
|
||||
* inline constexpr struct volume : quantity_spec<pow<3>(length)> {} volume;
|
||||
* inline constexpr struct velocity : quantity_spec<position_vector / duration> {} velocity;
|
||||
* inline constexpr struct speed : quantity_spec<length / time> {} speed;
|
||||
* inline constexpr struct force : quantity_spec<mass * acceleration, quantity_character::vector> {} force;
|
||||
* inline constexpr struct power : quantity_spec<force * velocity, quantity_character::scalar> {} power;
|
||||
* inline constexpr struct area final : quantity_spec<pow<2>(length)> {} area;
|
||||
* inline constexpr struct volume final : quantity_spec<pow<3>(length)> {} volume;
|
||||
* inline constexpr struct velocity final : quantity_spec<position_vector / duration> {} velocity;
|
||||
* inline constexpr struct speed final : quantity_spec<length / time> {} speed;
|
||||
* inline constexpr struct force final : quantity_spec<mass * acceleration, quantity_character::vector> {} force;
|
||||
* inline constexpr struct power final : quantity_spec<force * velocity, quantity_character::scalar> {} power;
|
||||
* @endcode
|
||||
*
|
||||
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
||||
@ -260,19 +261,32 @@ struct quantity_spec<Self, Dim, Args...> : detail::quantity_spec_interface<Self>
|
||||
* @tparam Args optionally a value of a `quantity_character` in case the base quantity should not be scalar
|
||||
*/
|
||||
#ifdef MP_UNITS_API_NO_CRTP
|
||||
template<detail::IntermediateDerivedQuantitySpec auto Eq, one_of<quantity_character> auto... Args>
|
||||
template<detail::DerivedQuantitySpec auto Eq, one_of<quantity_character> auto... Args>
|
||||
requires(... && !QuantitySpec<decltype(Args)>)
|
||||
struct quantity_spec<Eq, Args...> : detail::quantity_spec_interface {
|
||||
#else
|
||||
template<typename Self, detail::IntermediateDerivedQuantitySpec auto Eq, one_of<quantity_character> auto... Args>
|
||||
template<typename Self, detail::DerivedQuantitySpec auto Eq, one_of<quantity_character> auto... Args>
|
||||
requires(... && !QuantitySpec<decltype(Args)>)
|
||||
struct quantity_spec<Self, Eq, Args...> : detail::quantity_spec_interface<Self> {
|
||||
#endif
|
||||
using _base_type_ = quantity_spec;
|
||||
static constexpr auto _equation_ = Eq;
|
||||
static constexpr Dimension auto dimension = Eq.dimension;
|
||||
static constexpr quantity_character character = detail::quantity_character_init<Args...>(Eq.character);
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<QuantitySpec auto Q, bool = requires { Q._equation_; }>
|
||||
struct propagate_equation {};
|
||||
|
||||
template<QuantitySpec auto Q>
|
||||
struct propagate_equation<Q, true> {
|
||||
static constexpr auto _equation_ = Q._equation_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @brief Specialization defining a leaf quantity in the hierarchy
|
||||
*
|
||||
@ -285,10 +299,10 @@ struct quantity_spec<Self, Eq, Args...> : detail::quantity_spec_interface<Self>
|
||||
* For example:
|
||||
*
|
||||
* @code{.cpp}
|
||||
* inline constexpr struct width : quantity_spec<length> {} width;
|
||||
* inline constexpr struct height : quantity_spec<length> {} height;
|
||||
* inline constexpr struct diameter : quantity_spec<width> {} diameter;
|
||||
* inline constexpr struct position_vector : quantity_spec<length, quantity_character::vector> {} position_vector;
|
||||
* inline constexpr struct width final : quantity_spec<length> {} width;
|
||||
* inline constexpr struct height final : quantity_spec<length> {} height;
|
||||
* inline constexpr struct diameter final : quantity_spec<width> {} diameter;
|
||||
* inline constexpr struct position_vector final : quantity_spec<length, quantity_character::vector> {} position_vector;
|
||||
* @endcode
|
||||
*
|
||||
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
||||
@ -303,13 +317,15 @@ struct quantity_spec<Self, Eq, Args...> : detail::quantity_spec_interface<Self>
|
||||
#ifdef MP_UNITS_API_NO_CRTP
|
||||
template<detail::NamedQuantitySpec auto QS, one_of<quantity_character, struct is_kind> auto... Args>
|
||||
requires(... && !QuantitySpec<decltype(Args)>)
|
||||
struct quantity_spec<QS, Args...> : decltype(QS) {
|
||||
struct quantity_spec<QS, Args...> : detail::propagate_equation<QS>, detail::quantity_spec_interface {
|
||||
#else
|
||||
template<typename Self, detail::NamedQuantitySpec auto QS, one_of<quantity_character, struct is_kind> auto... Args>
|
||||
requires(... && !QuantitySpec<decltype(Args)>)
|
||||
struct quantity_spec<Self, QS, Args...> : decltype(QS) {
|
||||
struct quantity_spec<Self, QS, Args...> : detail::propagate_equation<QS>, detail::quantity_spec_interface<Self> {
|
||||
#endif
|
||||
using _base_type_ = quantity_spec;
|
||||
static constexpr auto _parent_ = QS;
|
||||
static constexpr Dimension auto dimension = _parent_.dimension;
|
||||
static constexpr quantity_character character = detail::quantity_character_init<Args...>(QS.character);
|
||||
|
||||
#ifndef MP_UNITS_API_NO_CRTP
|
||||
@ -330,6 +346,7 @@ struct quantity_spec<Self, QS, Args...> : decltype(QS) {
|
||||
#endif
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
/**
|
||||
* @brief Specialization defining a leaf derived quantity in the hierarchy and refining paren't equation
|
||||
*
|
||||
@ -343,10 +360,10 @@ struct quantity_spec<Self, QS, Args...> : decltype(QS) {
|
||||
* For example:
|
||||
*
|
||||
* @code{.cpp}
|
||||
* inline constexpr struct angular_measure : quantity_spec<dimensionless, arc_length / radius, is_kind> {}
|
||||
* angular_measure; inline constexpr struct velocity : quantity_spec<speed, position_vector / duration> {} velocity;
|
||||
* inline constexpr struct weight : quantity_spec<force, mass * acceleration_of_free_fall> {} weight;
|
||||
* inline constexpr struct kinetic_energy : quantity_spec<mechanical_energy, mass * pow<2>(speed)> {} kinetic_energy;
|
||||
* inline constexpr struct angular_measure final : quantity_spec<dimensionless, arc_length / radius, is_kind> {} angular_measure;
|
||||
* inline constexpr struct velocity final : quantity_spec<speed, position_vector / duration> {} velocity;
|
||||
* inline constexpr struct weight final : quantity_spec<force, mass * acceleration_of_free_fall> {} weight;
|
||||
* inline constexpr struct kinetic_energy final : quantity_spec<mechanical_energy, mass * pow<2>(speed)> {} kinetic_energy;
|
||||
* @endcode
|
||||
*
|
||||
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
||||
@ -358,25 +375,50 @@ struct quantity_spec<Self, QS, Args...> : decltype(QS) {
|
||||
* @tparam Args optionally a value of a `quantity_character` in case the base quantity should not be scalar
|
||||
* or `is_kind` in case the quantity starts a new hierarchy tree of a kind
|
||||
*/
|
||||
// clang-format on
|
||||
#ifdef MP_UNITS_API_NO_CRTP
|
||||
template<detail::NamedQuantitySpec auto QS, detail::IntermediateDerivedQuantitySpec auto Eq,
|
||||
template<detail::NamedQuantitySpec auto QS, detail::DerivedQuantitySpec auto Eq,
|
||||
one_of<quantity_character, struct is_kind> auto... Args>
|
||||
requires(!requires { QS._equation_; } || (requires {
|
||||
QS._equation_;
|
||||
} && (explicitly_convertible(Eq, QS._equation_)))) && (... && !QuantitySpec<decltype(Args)>)
|
||||
struct quantity_spec<QS, Eq, Args...> : quantity_spec<QS, Args...> {
|
||||
struct quantity_spec<QS, Eq, Args...> : detail::quantity_spec_interface {
|
||||
#else
|
||||
template<typename Self, detail::NamedQuantitySpec auto QS, detail::IntermediateDerivedQuantitySpec auto Eq,
|
||||
template<typename Self, detail::NamedQuantitySpec auto QS, detail::DerivedQuantitySpec auto Eq,
|
||||
one_of<quantity_character, struct is_kind> auto... Args>
|
||||
requires(!requires { QS._equation_; } || (requires {
|
||||
QS._equation_;
|
||||
} && (explicitly_convertible(Eq, QS._equation_)))) && (... && !QuantitySpec<decltype(Args)>)
|
||||
struct quantity_spec<Self, QS, Eq, Args...> : quantity_spec<Self, QS, Args...> {
|
||||
struct quantity_spec<Self, QS, Eq, Args...> : detail::quantity_spec_interface<Self> {
|
||||
#endif
|
||||
using _base_type_ = quantity_spec;
|
||||
static constexpr auto _parent_ = QS;
|
||||
static constexpr auto _equation_ = Eq;
|
||||
static constexpr Dimension auto dimension = _parent_.dimension;
|
||||
static constexpr quantity_character character = detail::quantity_character_init<Args...>(Eq.character);
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<detail::DerivedQuantitySpecExpr... Expr>
|
||||
struct derived_quantity_spec_impl :
|
||||
#ifdef MP_UNITS_API_NO_CRTP
|
||||
detail::quantity_spec_interface,
|
||||
#else
|
||||
detail::quantity_spec_interface<derived_quantity_spec<Expr...>>,
|
||||
#endif
|
||||
detail::expr_fractions<detail::is_dimensionless, Expr...> {
|
||||
using _base_type_ = derived_quantity_spec_impl;
|
||||
using _base_ = detail::expr_fractions<detail::is_dimensionless, Expr...>;
|
||||
|
||||
static constexpr Dimension auto dimension =
|
||||
detail::expr_map<detail::to_dimension, derived_dimension, struct dimension_one,
|
||||
detail::type_list_of_base_dimension_less>(_base_{});
|
||||
static constexpr quantity_character character =
|
||||
detail::derived_quantity_character(typename _base_::_num_{}, typename _base_::_den_{});
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @brief A specification of a derived quantity
|
||||
@ -421,22 +463,8 @@ struct quantity_spec<Self, QS, Eq, Args...> : quantity_spec<Self, QS, Args...> {
|
||||
* @note User should not instantiate this type! It is not exported from the C++ module. The library will
|
||||
* instantiate this type automatically based on the dimensional arithmetic equation provided by the user.
|
||||
*/
|
||||
template<detail::IntermediateDerivedQuantitySpecExpr... Expr>
|
||||
struct derived_quantity_spec :
|
||||
#ifdef MP_UNITS_API_NO_CRTP
|
||||
detail::quantity_spec_interface,
|
||||
#else
|
||||
detail::quantity_spec_interface<derived_quantity_spec<Expr...>>,
|
||||
#endif
|
||||
detail::expr_fractions<detail::is_dimensionless, Expr...> {
|
||||
using _base_ = detail::expr_fractions<detail::is_dimensionless, Expr...>;
|
||||
|
||||
static constexpr Dimension auto dimension =
|
||||
detail::expr_map<detail::to_dimension, derived_dimension, struct dimension_one,
|
||||
detail::type_list_of_base_dimension_less>(_base_{});
|
||||
static constexpr quantity_character character =
|
||||
detail::derived_quantity_character(typename _base_::_num_{}, typename _base_::_den_{});
|
||||
};
|
||||
template<detail::DerivedQuantitySpecExpr... Expr>
|
||||
struct derived_quantity_spec final : detail::derived_quantity_spec_impl<Expr...> {};
|
||||
|
||||
/**
|
||||
* @brief Quantity of dimension one
|
||||
@ -446,6 +474,13 @@ struct derived_quantity_spec :
|
||||
*/
|
||||
MP_UNITS_EXPORT QUANTITY_SPEC(dimensionless, derived_quantity_spec<>{});
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<>
|
||||
struct is_dimensionless<struct dimensionless> : std::true_type {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @brief Quantity kind specifier
|
||||
*
|
||||
@ -454,7 +489,7 @@ MP_UNITS_EXPORT QUANTITY_SPEC(dimensionless, derived_quantity_spec<>{});
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
concept QuantitySpecWithNoSpecifiers = detail::NamedQuantitySpec<T> || detail::IntermediateDerivedQuantitySpec<T>;
|
||||
concept QuantitySpecWithNoSpecifiers = detail::NamedQuantitySpec<T> || detail::DerivedQuantitySpec<T>;
|
||||
|
||||
template<QuantitySpec Q>
|
||||
[[nodiscard]] consteval QuantitySpec auto get_kind_tree_root(Q q);
|
||||
@ -464,7 +499,8 @@ template<QuantitySpec Q>
|
||||
#ifdef MP_UNITS_API_NO_CRTP
|
||||
template<typename Q>
|
||||
requires detail::QuantitySpecWithNoSpecifiers<Q> && (detail::get_kind_tree_root(Q{}) == Q{})
|
||||
struct kind_of_<Q> : Q {
|
||||
struct kind_of_<Q> final : Q::_base_type_ {
|
||||
using _base_type_ = kind_of_;
|
||||
static constexpr auto _quantity_spec_ = Q{};
|
||||
};
|
||||
#else
|
||||
@ -476,7 +512,8 @@ template<typename Q>
|
||||
template<detail::QuantitySpecWithNoSpecifiers Q>
|
||||
requires(detail::get_kind_tree_root(Q{}) == Q{})
|
||||
#endif
|
||||
struct kind_of_<Q> : quantity_spec<kind_of_<Q>, Q{}> {
|
||||
struct kind_of_<Q> final : quantity_spec<kind_of_<Q>, Q{}>::_base_type_ {
|
||||
using _base_type_ = kind_of_;
|
||||
static constexpr auto _quantity_spec_ = Q{};
|
||||
};
|
||||
#endif
|
||||
@ -487,9 +524,6 @@ inline constexpr kind_of_<MP_UNITS_REMOVE_CONST(decltype(Q))> kind_of;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<>
|
||||
struct is_dimensionless<struct dimensionless> : std::true_type {};
|
||||
|
||||
template<QuantitySpec auto... From, QuantitySpec Q>
|
||||
[[nodiscard]] consteval QuantitySpec auto clone_kind_of(Q q)
|
||||
{
|
||||
@ -556,7 +590,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, QuantitySpec Q>
|
||||
return dimensionless;
|
||||
else if constexpr (detail::ratio{Num, Den} == 1)
|
||||
return q;
|
||||
else if constexpr (detail::IntermediateDerivedQuantitySpec<Q>)
|
||||
else if constexpr (detail::DerivedQuantitySpec<Q>)
|
||||
return detail::clone_kind_of<Q{}>(
|
||||
detail::expr_pow<Num, Den, derived_quantity_spec, struct dimensionless, detail::type_list_of_quantity_spec_less>(
|
||||
detail::remove_kind(q)));
|
||||
@ -590,8 +624,6 @@ MP_UNITS_EXPORT_END
|
||||
|
||||
namespace detail {
|
||||
|
||||
enum class specs_convertible_result : std::int8_t { no, cast, explicit_conversion, yes };
|
||||
|
||||
template<QuantitySpec Q>
|
||||
[[nodiscard]] consteval int get_complexity(Q);
|
||||
|
||||
@ -616,7 +648,7 @@ template<typename Q>
|
||||
template<QuantitySpec Q>
|
||||
[[nodiscard]] consteval int get_complexity(Q)
|
||||
{
|
||||
if constexpr (detail::IntermediateDerivedQuantitySpec<Q>)
|
||||
if constexpr (detail::DerivedQuantitySpec<Q>)
|
||||
return get_complexity(typename Q::_num_{}) + get_complexity(typename Q::_den_{});
|
||||
else if constexpr (requires { Q::_equation_; })
|
||||
return 1 + get_complexity(Q::_equation_);
|
||||
@ -659,6 +691,8 @@ template<QuantitySpec Q>
|
||||
return true;
|
||||
}
|
||||
|
||||
enum class specs_convertible_result : std::int8_t { no, cast, explicit_conversion, yes };
|
||||
|
||||
template<QuantitySpec Q>
|
||||
struct explode_to_equation_result {
|
||||
Q equation;
|
||||
@ -709,7 +743,7 @@ explode_result(Q) -> explode_result<Q>;
|
||||
|
||||
#endif
|
||||
|
||||
template<int Complexity, IntermediateDerivedQuantitySpec Q>
|
||||
template<int Complexity, DerivedQuantitySpec Q>
|
||||
[[nodiscard]] consteval auto explode(Q q);
|
||||
|
||||
template<int Complexity, NamedQuantitySpec Q>
|
||||
@ -771,7 +805,7 @@ template<int Complexity, QuantitySpec Q>
|
||||
return explode_result{dimensionless};
|
||||
}
|
||||
|
||||
template<int Complexity, IntermediateDerivedQuantitySpec Q>
|
||||
template<int Complexity, DerivedQuantitySpec Q>
|
||||
[[nodiscard]] consteval auto explode(Q q)
|
||||
{
|
||||
constexpr auto c = get_complexity(Q{});
|
||||
@ -1304,7 +1338,7 @@ template<typename... DensTo>
|
||||
return specs_convertible_result::yes;
|
||||
}
|
||||
|
||||
template<IntermediateDerivedQuantitySpec From, IntermediateDerivedQuantitySpec To>
|
||||
template<DerivedQuantitySpec From, DerivedQuantitySpec To>
|
||||
[[nodiscard]] consteval specs_convertible_result are_ingredients_convertible(From, To)
|
||||
{
|
||||
return are_ingredients_convertible(type_list_sort<typename From::_num_, type_list_of_ingredients_less>{},
|
||||
@ -1313,7 +1347,7 @@ template<IntermediateDerivedQuantitySpec From, IntermediateDerivedQuantitySpec T
|
||||
type_list_sort<typename To::_den_, type_list_of_ingredients_less>{});
|
||||
}
|
||||
|
||||
template<IntermediateDerivedQuantitySpec From, NamedQuantitySpec To>
|
||||
template<DerivedQuantitySpec From, NamedQuantitySpec To>
|
||||
[[nodiscard]] consteval specs_convertible_result are_ingredients_convertible(From, To)
|
||||
{
|
||||
return are_ingredients_convertible(type_list_sort<typename From::_num_, type_list_of_ingredients_less>{},
|
||||
@ -1321,7 +1355,7 @@ template<IntermediateDerivedQuantitySpec From, NamedQuantitySpec To>
|
||||
type_list<To>{}, type_list<>{});
|
||||
}
|
||||
|
||||
template<NamedQuantitySpec From, IntermediateDerivedQuantitySpec To>
|
||||
template<NamedQuantitySpec From, DerivedQuantitySpec To>
|
||||
[[nodiscard]] consteval specs_convertible_result are_ingredients_convertible(From, To)
|
||||
{
|
||||
return are_ingredients_convertible(type_list<From>{}, type_list<>{},
|
||||
@ -1353,8 +1387,8 @@ template<NamedQuantitySpec From, NamedQuantitySpec To>
|
||||
using enum specs_convertible_result;
|
||||
|
||||
if constexpr (have_common_base(From{}, To{})) {
|
||||
if constexpr (std::derived_from<From, To>) return yes;
|
||||
if constexpr (std::derived_from<To, From>) return explicit_conversion;
|
||||
if constexpr (is_child_of(From{}, To{})) return yes;
|
||||
if constexpr (is_child_of(To{}, From{})) return explicit_conversion;
|
||||
if constexpr (get_kind(From{}) == get_kind(To{})) return cast;
|
||||
return no;
|
||||
} else if constexpr (get_kind(From{}) != get_kind(To{}))
|
||||
@ -1385,9 +1419,9 @@ template<QuantitySpec From, QuantitySpec To>
|
||||
return yes;
|
||||
else if constexpr (NamedQuantitySpec<From> && NamedQuantitySpec<To>) {
|
||||
return convertible_named(from, to);
|
||||
} else if constexpr (IntermediateDerivedQuantitySpec<From> && IntermediateDerivedQuantitySpec<To>) {
|
||||
} else if constexpr (DerivedQuantitySpec<From> && DerivedQuantitySpec<To>) {
|
||||
return are_ingredients_convertible(from, to);
|
||||
} else if constexpr (IntermediateDerivedQuantitySpec<From>) {
|
||||
} else if constexpr (DerivedQuantitySpec<From>) {
|
||||
auto res = explode<get_complexity(to)>(from);
|
||||
if constexpr (NamedQuantitySpec<decltype(res.quantity)>)
|
||||
return convertible_impl(res.quantity, to);
|
||||
@ -1396,7 +1430,7 @@ template<QuantitySpec From, QuantitySpec To>
|
||||
return min(eq.result, convertible_impl(res.quantity, eq.equation));
|
||||
} else
|
||||
return are_ingredients_convertible(from, to);
|
||||
} else if constexpr (IntermediateDerivedQuantitySpec<To>) {
|
||||
} else if constexpr (DerivedQuantitySpec<To>) {
|
||||
auto res = explode<get_complexity(from)>(to);
|
||||
if constexpr (NamedQuantitySpec<decltype(res.quantity)>)
|
||||
return min(res.result, convertible_impl(from, res.quantity));
|
||||
@ -1473,7 +1507,7 @@ template<QuantitySpec Q>
|
||||
return q;
|
||||
} else if constexpr (requires { Q::_parent_; }) {
|
||||
return get_kind_tree_root(Q::_parent_);
|
||||
} else if constexpr (detail::IntermediateDerivedQuantitySpec<Q>) {
|
||||
} else if constexpr (detail::DerivedQuantitySpec<Q>) {
|
||||
return detail::expr_map<detail::to_kind, derived_quantity_spec, struct dimensionless,
|
||||
detail::type_list_of_quantity_spec_less>(q);
|
||||
} else {
|
||||
@ -1511,11 +1545,11 @@ template<QuantitySpec Q1, QuantitySpec Q2>
|
||||
else if constexpr (detail::NestedQuantityKindSpecOf<Q2{}, Q1{}>)
|
||||
return detail::remove_kind(q2);
|
||||
else if constexpr ((detail::QuantityKindSpec<Q1> && !detail::QuantityKindSpec<Q2>) ||
|
||||
(detail::IntermediateDerivedQuantitySpec<QQ1> && detail::NamedQuantitySpec<QQ2> &&
|
||||
(detail::DerivedQuantitySpec<QQ1> && detail::NamedQuantitySpec<QQ2> &&
|
||||
implicitly_convertible(Q1{}, Q2{})))
|
||||
return q2;
|
||||
else if constexpr ((!detail::QuantityKindSpec<Q1> && detail::QuantityKindSpec<Q2>) ||
|
||||
(detail::NamedQuantitySpec<QQ1> && detail::IntermediateDerivedQuantitySpec<QQ2> &&
|
||||
(detail::NamedQuantitySpec<QQ1> && detail::DerivedQuantitySpec<QQ2> &&
|
||||
implicitly_convertible(Q2{}, Q1{})))
|
||||
return q1;
|
||||
else if constexpr (detail::have_common_base(Q1{}, Q2{}))
|
||||
|
@ -64,25 +64,14 @@ template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_quantity_spec =
|
||||
requires(T* t) { to_base_specialization_of_quantity_spec(t); };
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_quantity_spec = false;
|
||||
|
||||
#ifdef MP_UNITS_API_NO_CRTP
|
||||
template<auto... Args>
|
||||
inline constexpr bool is_specialization_of_quantity_spec<quantity_spec<Args...>> = true;
|
||||
#else
|
||||
template<typename T, auto... Args>
|
||||
inline constexpr bool is_specialization_of_quantity_spec<quantity_spec<T, Args...>> = true;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Concept matching all named quantity specification types
|
||||
*
|
||||
* Satisfied by all types that derive from `quantity_spec`.
|
||||
*/
|
||||
template<typename T>
|
||||
concept NamedQuantitySpec = is_derived_from_specialization_of_quantity_spec<T> &&
|
||||
(!is_specialization_of_quantity_spec<T>)&&(!QuantityKindSpec<T>);
|
||||
concept NamedQuantitySpec =
|
||||
is_derived_from_specialization_of_quantity_spec<T> && std::is_final_v<T> && (!QuantityKindSpec<T>);
|
||||
|
||||
template<typename T>
|
||||
struct is_dimensionless : std::false_type {};
|
||||
@ -101,13 +90,12 @@ inline constexpr bool is_per_of_quantity_specs<per<Ts...>> =
|
||||
(... && (NamedQuantitySpec<Ts> || is_dimensionless<Ts>::value || is_power_of_quantity_spec<Ts>));
|
||||
|
||||
template<typename T>
|
||||
concept IntermediateDerivedQuantitySpecExpr =
|
||||
detail::NamedQuantitySpec<T> || detail::is_dimensionless<T>::value || detail::is_power_of_quantity_spec<T> ||
|
||||
detail::is_per_of_quantity_specs<T>;
|
||||
concept DerivedQuantitySpecExpr = detail::NamedQuantitySpec<T> || detail::is_dimensionless<T>::value ||
|
||||
detail::is_power_of_quantity_spec<T> || detail::is_per_of_quantity_specs<T>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<detail::IntermediateDerivedQuantitySpecExpr... Expr>
|
||||
template<detail::DerivedQuantitySpecExpr... Expr>
|
||||
struct derived_quantity_spec;
|
||||
|
||||
namespace detail {
|
||||
@ -121,7 +109,7 @@ namespace detail {
|
||||
* explicitly not supported here.
|
||||
*/
|
||||
template<typename T>
|
||||
concept IntermediateDerivedQuantitySpec =
|
||||
concept DerivedQuantitySpec =
|
||||
is_specialization_of<T, derived_quantity_spec> ||
|
||||
(QuantityKindSpec<T> &&
|
||||
is_specialization_of<std::remove_const_t<decltype(T::_quantity_spec_)>, derived_quantity_spec>);
|
||||
@ -130,20 +118,21 @@ concept IntermediateDerivedQuantitySpec =
|
||||
|
||||
|
||||
MP_UNITS_EXPORT template<typename T>
|
||||
concept QuantitySpec =
|
||||
detail::NamedQuantitySpec<T> || detail::IntermediateDerivedQuantitySpec<T> || detail::QuantityKindSpec<T>;
|
||||
concept QuantitySpec = detail::NamedQuantitySpec<T> || detail::DerivedQuantitySpec<T> || detail::QuantityKindSpec<T>;
|
||||
|
||||
MP_UNITS_EXPORT template<QuantitySpec Q>
|
||||
[[nodiscard]] consteval detail::QuantityKindSpec auto get_kind(Q q);
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<auto To, auto From>
|
||||
concept NestedQuantityKindSpecOf =
|
||||
QuantitySpec<decltype(From)> && QuantitySpec<decltype(To)> && get_kind(From) != get_kind(To) &&
|
||||
std::derived_from<decltype(To), std::remove_const_t<decltype(get_kind(From)._quantity_spec_)>>;
|
||||
template<QuantitySpec Child, QuantitySpec Parent>
|
||||
[[nodiscard]] consteval bool is_child_of(Child ch, Parent p);
|
||||
|
||||
}
|
||||
template<auto To, auto From>
|
||||
concept NestedQuantityKindSpecOf = QuantitySpec<decltype(From)> && QuantitySpec<decltype(To)> &&
|
||||
get_kind(From) != get_kind(To) && is_child_of(To, get_kind(From)._quantity_spec_);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
MP_UNITS_EXPORT template<typename T, auto QS>
|
||||
concept QuantitySpecOf =
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <mp-units/ext/fixed_string.h>
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
#include <mp-units/ext/contracts.h>
|
||||
#include <compare> // IWYU pragma: export
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
@ -45,10 +45,10 @@ namespace mp_units {
|
||||
* @code{.cpp}
|
||||
* // hypothetical natural system of units for c=1
|
||||
*
|
||||
* inline constexpr struct second : named_unit<"s"> {} second;
|
||||
* inline constexpr struct minute : named_unit<"min", mag<60> * second> {} minute;
|
||||
* inline constexpr struct gram : named_unit<"g"> {} gram;
|
||||
* inline constexpr struct kilogram : decltype(si::kilo<gram>) {} kilogram;
|
||||
* inline constexpr struct second final : named_unit<"s"> {} second;
|
||||
* inline constexpr struct minute final : named_unit<"min", mag<60> * second> {} minute;
|
||||
* inline constexpr struct gram final : named_unit<"g"> {} gram;
|
||||
* inline constexpr auto kilogram = si::kilo<gram>;
|
||||
*
|
||||
* inline constexpr struct time : system_reference<isq::time, second> {} time;
|
||||
* inline constexpr struct length : system_reference<isq::length, second> {} length;
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <mp-units/framework/unit_concepts.h>
|
||||
|
||||
#ifndef MP_UNITS_IN_MODULE_INTERFACE
|
||||
#include <mp-units/ext/contracts.h>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
@ -62,6 +63,13 @@ struct propagate_point_origin<U, true> {
|
||||
static constexpr auto point_origin = U::point_origin;
|
||||
};
|
||||
|
||||
template<Magnitude auto M, Unit U>
|
||||
struct scaled_unit_impl : detail::propagate_point_origin<U> {
|
||||
using _base_type_ = scaled_unit_impl; // exposition only
|
||||
static constexpr MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(Magnitude) auto mag = M;
|
||||
static constexpr U reference_unit{};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
@ -74,10 +82,7 @@ struct propagate_point_origin<U, true> {
|
||||
* instantiate this type automatically based on the unit arithmetic equation provided by the user.
|
||||
*/
|
||||
template<Magnitude auto M, Unit U>
|
||||
struct scaled_unit : detail::propagate_point_origin<U> {
|
||||
static constexpr MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(Magnitude) auto mag = M;
|
||||
static constexpr U reference_unit{};
|
||||
};
|
||||
struct scaled_unit final : detail::scaled_unit_impl<M, U> {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
@ -100,12 +105,12 @@ inline constexpr bool is_specialization_of_scaled_unit<scaled_unit<M, U>> = true
|
||||
* For example:
|
||||
*
|
||||
* @code{.cpp}
|
||||
* inline constexpr struct second : named_unit<"s", time> {} second;
|
||||
* inline constexpr struct metre : named_unit<"m", length> {} metre;
|
||||
* inline constexpr struct hertz : named_unit<"Hz", inverse(second)> {} hertz;
|
||||
* inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
||||
* inline constexpr struct degree_Celsius : named_unit<{u8"°C", "`C"}, kelvin> {} degree_Celsius;
|
||||
* inline constexpr struct minute : named_unit<"min", mag<60> * second> {} minute;
|
||||
* inline constexpr struct second final : named_unit<"s", kind_of<time>> {} second;
|
||||
* inline constexpr struct metre final : named_unit<"m", kind_of<length> {} metre;
|
||||
* inline constexpr struct hertz final : named_unit<"Hz", inverse(second), kind_of<frequency>> {} hertz;
|
||||
* inline constexpr struct newton final : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
||||
* inline constexpr struct degree_Celsius final : named_unit<{u8"°C", "`C"}, kelvin, zeroth_degree_Celsius> {}
|
||||
* degree_Celsius; inline constexpr struct minute final : named_unit<"min", mag<60> * second> {} minute;
|
||||
* @endcode
|
||||
*
|
||||
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
||||
@ -137,6 +142,7 @@ struct named_unit;
|
||||
template<symbol_text Symbol, detail::QuantityKindSpec auto QS>
|
||||
requires(!Symbol.empty()) && detail::BaseDimension<std::remove_const_t<decltype(QS.dimension)>>
|
||||
struct named_unit<Symbol, QS> {
|
||||
using _base_type_ = named_unit; // exposition only
|
||||
static constexpr auto symbol = Symbol; ///< Unique base unit identifier
|
||||
static constexpr auto quantity_spec = QS;
|
||||
};
|
||||
@ -144,6 +150,7 @@ struct named_unit<Symbol, QS> {
|
||||
template<symbol_text Symbol, detail::QuantityKindSpec auto QS, PointOrigin auto PO>
|
||||
requires(!Symbol.empty()) && detail::BaseDimension<std::remove_const_t<decltype(QS.dimension)>>
|
||||
struct named_unit<Symbol, QS, PO> {
|
||||
using _base_type_ = named_unit; // exposition only
|
||||
static constexpr auto symbol = Symbol; ///< Unique base unit identifier
|
||||
static constexpr auto quantity_spec = QS;
|
||||
static constexpr auto point_origin = PO;
|
||||
@ -162,6 +169,7 @@ struct named_unit<Symbol, QS, PO> {
|
||||
template<symbol_text Symbol>
|
||||
requires(!Symbol.empty())
|
||||
struct named_unit<Symbol> {
|
||||
using _base_type_ = named_unit; // exposition only
|
||||
static constexpr auto symbol = Symbol; ///< Unique base unit identifier
|
||||
};
|
||||
|
||||
@ -175,13 +183,15 @@ struct named_unit<Symbol> {
|
||||
*/
|
||||
template<symbol_text Symbol, Unit auto U>
|
||||
requires(!Symbol.empty())
|
||||
struct named_unit<Symbol, U> : decltype(U) {
|
||||
struct named_unit<Symbol, U> : decltype(U)::_base_type_ {
|
||||
using _base_type_ = named_unit; // exposition only
|
||||
static constexpr auto symbol = Symbol; ///< Unique unit identifier
|
||||
};
|
||||
|
||||
template<symbol_text Symbol, Unit auto U, PointOrigin auto PO>
|
||||
requires(!Symbol.empty())
|
||||
struct named_unit<Symbol, U, PO> : decltype(U) {
|
||||
struct named_unit<Symbol, U, PO> : decltype(U)::_base_type_ {
|
||||
using _base_type_ = named_unit; // exposition only
|
||||
static constexpr auto symbol = Symbol; ///< Unique unit identifier
|
||||
static constexpr auto point_origin = PO;
|
||||
};
|
||||
@ -197,14 +207,16 @@ struct named_unit<Symbol, U, PO> : decltype(U) {
|
||||
*/
|
||||
template<symbol_text Symbol, AssociatedUnit auto U, detail::QuantityKindSpec auto QS>
|
||||
requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension)
|
||||
struct named_unit<Symbol, U, QS> : decltype(U) {
|
||||
struct named_unit<Symbol, U, QS> : decltype(U)::_base_type_ {
|
||||
using _base_type_ = named_unit; // exposition only
|
||||
static constexpr auto symbol = Symbol; ///< Unique unit identifier
|
||||
static constexpr auto quantity_spec = QS;
|
||||
};
|
||||
|
||||
template<symbol_text Symbol, AssociatedUnit auto U, detail::QuantityKindSpec auto QS, PointOrigin auto PO>
|
||||
requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension)
|
||||
struct named_unit<Symbol, U, QS, PO> : decltype(U) {
|
||||
struct named_unit<Symbol, U, QS, PO> : decltype(U)::_base_type_ {
|
||||
using _base_type_ = named_unit; // exposition only
|
||||
static constexpr auto symbol = Symbol; ///< Unique unit identifier
|
||||
static constexpr auto quantity_spec = QS;
|
||||
static constexpr auto point_origin = PO;
|
||||
@ -225,7 +237,7 @@ struct named_unit<Symbol, U, QS, PO> : decltype(U) {
|
||||
* template<PrefixableUnit auto U>
|
||||
* inline constexpr kilo_<U> kilo;
|
||||
*
|
||||
* inline constexpr struct kilogram : decltype(si::kilo<gram>) {} kilogram;
|
||||
* inline constexpr auto kilogram = si::kilo<gram>;
|
||||
* @endcode
|
||||
*
|
||||
* @tparam Symbol a prefix text to prepend to a unit symbol
|
||||
@ -234,7 +246,8 @@ struct named_unit<Symbol, U, QS, PO> : decltype(U) {
|
||||
*/
|
||||
MP_UNITS_EXPORT template<symbol_text Symbol, Magnitude auto M, PrefixableUnit auto U>
|
||||
requires(!Symbol.empty())
|
||||
struct prefixed_unit : decltype(M * U) {
|
||||
struct prefixed_unit : decltype(M * U)::_base_type_ {
|
||||
using _base_type_ = prefixed_unit; // exposition only
|
||||
static constexpr auto symbol = Symbol + U.symbol;
|
||||
};
|
||||
|
||||
@ -243,6 +256,11 @@ namespace detail {
|
||||
template<typename T>
|
||||
struct is_one : std::false_type {};
|
||||
|
||||
template<DerivedUnitExpr... Expr>
|
||||
struct derived_unit_impl : detail::expr_fractions<detail::is_one, Expr...> {
|
||||
using _base_type_ = derived_unit_impl; // exposition only
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
@ -291,7 +309,7 @@ struct is_one : std::false_type {};
|
||||
* instantiate this type automatically based on the unit arithmetic equation provided by the user.
|
||||
*/
|
||||
template<detail::DerivedUnitExpr... Expr>
|
||||
struct derived_unit : detail::expr_fractions<detail::is_one, Expr...> {};
|
||||
struct derived_unit final : detail::derived_unit_impl<Expr...> {};
|
||||
|
||||
/**
|
||||
* @brief Unit one
|
||||
@ -299,7 +317,7 @@ struct derived_unit : detail::expr_fractions<detail::is_one, Expr...> {};
|
||||
* Unit of a dimensionless quantity.
|
||||
*/
|
||||
// clang-format off
|
||||
MP_UNITS_EXPORT inline constexpr struct one : derived_unit<> {} one;
|
||||
MP_UNITS_EXPORT inline constexpr struct one final : detail::derived_unit_impl<> {} one;
|
||||
// clang-format on
|
||||
|
||||
namespace detail {
|
||||
@ -334,9 +352,6 @@ canonical_unit(M, U) -> canonical_unit<M, U>;
|
||||
|
||||
#endif
|
||||
|
||||
template<Unit T, symbol_text Symbol, detail::QuantityKindSpec auto Q, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Q, Args...>&);
|
||||
|
||||
template<Unit T, symbol_text Symbol, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Args...>&);
|
||||
|
||||
@ -347,21 +362,15 @@ template<typename T, typename F, int Num, int... Den>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const power<F, Num, Den...>&);
|
||||
|
||||
template<Unit T, typename... Expr>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const derived_unit<Expr...>&);
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const derived_unit_impl<Expr...>&);
|
||||
|
||||
template<Unit T, auto M, typename U>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const scaled_unit<M, U>&)
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const scaled_unit_impl<M, U>&)
|
||||
{
|
||||
auto base = get_canonical_unit_impl(U{}, U{});
|
||||
return canonical_unit{M * base.mag, base.reference_unit};
|
||||
}
|
||||
|
||||
template<Unit T, symbol_text Symbol, detail::QuantityKindSpec auto Q, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Q, Args...>&)
|
||||
{
|
||||
return canonical_unit{mag<1>, t};
|
||||
}
|
||||
|
||||
template<Unit T, symbol_text Symbol, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Args...>&)
|
||||
{
|
||||
@ -405,7 +414,7 @@ template<typename... Us>
|
||||
}
|
||||
|
||||
template<Unit T, typename... Expr>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const derived_unit<Expr...>&)
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const derived_unit_impl<Expr...>&)
|
||||
{
|
||||
auto num = get_canonical_unit_impl(typename derived_unit<Expr...>::_num_{});
|
||||
auto den = get_canonical_unit_impl(typename derived_unit<Expr...>::_den_{});
|
||||
@ -493,43 +502,13 @@ MP_UNITS_EXPORT_END
|
||||
|
||||
namespace detail {
|
||||
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(...) { return false; }
|
||||
|
||||
template<symbol_text Symbol, auto... D>
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const named_unit<Symbol, D...>&,
|
||||
const named_unit<Symbol, D...>&)
|
||||
template<Unit U1, Unit U2>
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit(U1 u1, U2 u2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename F1, typename F2, auto... Vs>
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const power<F1, Vs...>&, const power<F2, Vs...>&)
|
||||
{
|
||||
return have_same_canonical_reference_unit_impl(F1{}, F2{});
|
||||
}
|
||||
|
||||
template<typename... Us1, typename... Us2>
|
||||
requires(sizeof...(Us1) == sizeof...(Us2))
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const type_list<Us1...>&, const type_list<Us2...>&)
|
||||
{
|
||||
return (... && have_same_canonical_reference_unit_impl(Us1{}, Us2{}));
|
||||
}
|
||||
|
||||
template<typename... Expr1, typename... Expr2>
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const derived_unit<Expr1...>&,
|
||||
const derived_unit<Expr2...>&)
|
||||
{
|
||||
return have_same_canonical_reference_unit_impl(typename derived_unit<Expr1...>::_num_{},
|
||||
typename derived_unit<Expr2...>::_num_{}) &&
|
||||
have_same_canonical_reference_unit_impl(typename derived_unit<Expr1...>::_den_{},
|
||||
typename derived_unit<Expr2...>::_den_{});
|
||||
}
|
||||
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit(Unit auto u1, Unit auto u2)
|
||||
{
|
||||
auto canonical_lhs = get_canonical_unit(u1);
|
||||
auto canonical_rhs = get_canonical_unit(u2);
|
||||
return have_same_canonical_reference_unit_impl(canonical_lhs.reference_unit, canonical_rhs.reference_unit);
|
||||
if constexpr (is_same_v<U1, U2>)
|
||||
return true;
|
||||
else
|
||||
return is_same_v<decltype(get_canonical_unit(u1).reference_unit), decltype(get_canonical_unit(u2).reference_unit)>;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@ -621,17 +600,21 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
|
||||
|
||||
// common dimensionless units
|
||||
// clang-format off
|
||||
inline constexpr struct percent : named_unit<"%", mag_ratio<1, 100> * one> {} percent;
|
||||
inline constexpr struct per_mille : named_unit<symbol_text{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<symbol_text{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;
|
||||
// clang-format on
|
||||
|
||||
|
||||
// convertible_to
|
||||
[[nodiscard]] consteval bool convertible(Unit auto from, Unit auto to)
|
||||
template<Unit U1, Unit U2>
|
||||
[[nodiscard]] consteval bool convertible(U1 from, U2 to)
|
||||
{
|
||||
return detail::have_same_canonical_reference_unit(from, to);
|
||||
if constexpr (is_same_v<U1, U2>)
|
||||
return true;
|
||||
else
|
||||
return detail::have_same_canonical_reference_unit(from, to);
|
||||
}
|
||||
|
||||
// Common unit
|
||||
@ -641,10 +624,12 @@ template<Unit U1, Unit U2>
|
||||
[[nodiscard]] consteval Unit auto common_unit(U1 u1, U2 u2)
|
||||
requires(detail::have_same_canonical_reference_unit(u1, u2))
|
||||
{
|
||||
if constexpr (U1{} == U2{}) {
|
||||
if constexpr (std::derived_from<U1, U2>)
|
||||
if constexpr (is_same_v<U1, U2>)
|
||||
return u1;
|
||||
else if constexpr (U1{} == U2{}) {
|
||||
if constexpr (std::derived_from<U1, typename U2::_base_type_>)
|
||||
return u1;
|
||||
else if constexpr (std::derived_from<U2, U1>)
|
||||
else if constexpr (std::derived_from<U2, typename U1::_base_type_>)
|
||||
return u2;
|
||||
else
|
||||
// TODO Check if there is a better choice here
|
||||
@ -738,7 +723,7 @@ constexpr Out unit_symbol_impl(Out out, U, const unit_symbol_formatting& fmt, bo
|
||||
}
|
||||
|
||||
template<typename CharT, std::output_iterator<CharT> Out, auto M, typename U>
|
||||
constexpr Out unit_symbol_impl(Out out, const scaled_unit<M, U>& u, const unit_symbol_formatting& fmt,
|
||||
constexpr Out unit_symbol_impl(Out out, const scaled_unit_impl<M, U>& u, const unit_symbol_formatting& fmt,
|
||||
bool negative_power)
|
||||
{
|
||||
if constexpr (M == mag<1>) {
|
||||
@ -807,13 +792,13 @@ constexpr Out unit_symbol_impl(Out out, const type_list<Nums...>& nums, const ty
|
||||
}
|
||||
|
||||
template<typename CharT, std::output_iterator<CharT> Out, typename... Expr>
|
||||
constexpr Out unit_symbol_impl(Out out, const derived_unit<Expr...>&, const unit_symbol_formatting& fmt,
|
||||
constexpr Out unit_symbol_impl(Out out, const derived_unit_impl<Expr...>&, const unit_symbol_formatting& fmt,
|
||||
bool negative_power)
|
||||
{
|
||||
(void)negative_power;
|
||||
MP_UNITS_EXPECTS(negative_power == false);
|
||||
return unit_symbol_impl<CharT>(out, typename derived_unit<Expr...>::_num_{}, typename derived_unit<Expr...>::_den_{},
|
||||
fmt);
|
||||
return unit_symbol_impl<CharT>(out, typename derived_unit_impl<Expr...>::_num_{},
|
||||
typename derived_unit_impl<Expr...>::_den_{}, fmt);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
@ -33,9 +33,8 @@ namespace mp_units {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// do not refactor below to a variable template - GCC-11 does not like it
|
||||
template<typename T>
|
||||
struct is_unit : std::false_type {};
|
||||
inline constexpr bool is_unit = false;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@ -45,7 +44,7 @@ struct is_unit : std::false_type {};
|
||||
* Satisfied by all unit types provided by the library.
|
||||
*/
|
||||
MP_UNITS_EXPORT template<typename T>
|
||||
concept Unit = detail::is_unit<T>::value;
|
||||
concept Unit = detail::is_unit<T>;
|
||||
|
||||
template<Magnitude auto M, Unit U>
|
||||
struct scaled_unit;
|
||||
@ -53,6 +52,8 @@ struct scaled_unit;
|
||||
MP_UNITS_EXPORT template<symbol_text Symbol, auto...>
|
||||
struct named_unit;
|
||||
|
||||
MP_UNITS_EXPORT struct one;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<symbol_text Symbol, auto... Args>
|
||||
@ -127,25 +128,17 @@ void is_unit_impl(const scaled_unit<M, U>*);
|
||||
template<symbol_text Symbol, auto... Args>
|
||||
void is_unit_impl(const named_unit<Symbol, Args...>*);
|
||||
|
||||
template<symbol_text Symbol, auto M, auto U>
|
||||
void is_unit_impl(const prefixed_unit<Symbol, M, U>*);
|
||||
|
||||
template<typename... Expr>
|
||||
void is_unit_impl(const derived_unit<Expr...>*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_unit = false;
|
||||
|
||||
template<symbol_text Symbol, auto... Args>
|
||||
inline constexpr bool is_specialization_of_unit<named_unit<Symbol, Args...>> = true;
|
||||
void is_unit_impl(const one*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_prefixed_unit = false;
|
||||
|
||||
template<symbol_text Symbol, Magnitude auto M, PrefixableUnit auto U>
|
||||
inline constexpr bool is_specialization_of_prefixed_unit<prefixed_unit<Symbol, M, U>> = true;
|
||||
|
||||
template<typename T>
|
||||
requires requires(T* t) { is_unit_impl(t); } && (!is_specialization_of_named_unit<T>) &&
|
||||
(!is_specialization_of_prefixed_unit<T>)
|
||||
struct is_unit<T> : std::true_type {};
|
||||
requires requires(T* t) { is_unit_impl(t); } && std::is_final_v<T>
|
||||
inline constexpr bool is_unit<T> = true;
|
||||
|
||||
template<Unit U>
|
||||
[[nodiscard]] consteval bool has_associated_quantity(U);
|
||||
@ -197,7 +190,8 @@ concept UnitOf =
|
||||
|
||||
namespace detail {
|
||||
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit(Unit auto u1, Unit auto u2);
|
||||
template<Unit U1, Unit U2>
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit(U1 u1, U2 u2);
|
||||
|
||||
}
|
||||
|
||||
@ -210,7 +204,7 @@ namespace detail {
|
||||
MP_UNITS_EXPORT template<typename U, auto U2, auto QS>
|
||||
concept UnitCompatibleWith =
|
||||
Unit<U> && Unit<MP_UNITS_REMOVE_CONST(decltype(U2))> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> &&
|
||||
(!AssociatedUnit<U> || UnitOf<U, QS>)&&detail::have_same_canonical_reference_unit(U{}, U2);
|
||||
(!AssociatedUnit<U> || UnitOf<U, QS>)&&(detail::have_same_canonical_reference_unit(U{}, U2));
|
||||
|
||||
|
||||
} // namespace mp_units
|
||||
|
@ -1,3 +1,25 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
module;
|
||||
|
||||
#include <mp-units/bits/core_gmf.h>
|
||||
|
@ -1,3 +1,25 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
module;
|
||||
|
||||
export module mp_units;
|
||||
|
@ -34,15 +34,15 @@ MP_UNITS_EXPORT
|
||||
namespace mp_units::angular {
|
||||
|
||||
// clang-format off
|
||||
inline constexpr struct dim_angle : base_dimension<"A"> {} dim_angle;
|
||||
inline constexpr struct dim_angle final : base_dimension<"A"> {} dim_angle;
|
||||
QUANTITY_SPEC(angle, dim_angle);
|
||||
QUANTITY_SPEC(solid_angle, pow<2>(angle));
|
||||
|
||||
inline constexpr struct radian : named_unit<"rad", kind_of<angle>> {} radian;
|
||||
inline constexpr struct revolution : named_unit<"rev", mag<2> * mag_pi * radian> {} revolution;
|
||||
inline constexpr struct degree : named_unit<symbol_text{u8"°", "deg"}, mag_ratio<1, 360> * revolution> {} degree;
|
||||
inline constexpr struct gradian : named_unit<symbol_text{u8"ᵍ", "grad"}, mag_ratio<1, 400> * revolution> {} gradian;
|
||||
inline constexpr struct steradian : named_unit<"sr", square(radian)> {} steradian;
|
||||
inline constexpr struct radian final : named_unit<"rad", kind_of<angle>> {} radian;
|
||||
inline constexpr struct revolution final : named_unit<"rev", mag<2> * mag_pi * radian> {} revolution;
|
||||
inline constexpr struct degree final : named_unit<symbol_text{u8"°", "deg"}, mag_ratio<1, 360> * revolution> {} degree;
|
||||
inline constexpr struct gradian final : named_unit<symbol_text{u8"ᵍ", "grad"}, mag_ratio<1, 400> * revolution> {} gradian;
|
||||
inline constexpr struct steradian final : named_unit<"sr", square(radian)> {} steradian;
|
||||
// clang-format on
|
||||
|
||||
namespace unit_symbols {
|
||||
|
@ -35,20 +35,16 @@ MP_UNITS_EXPORT
|
||||
namespace mp_units::cgs {
|
||||
|
||||
// clang-format off
|
||||
#if MP_UNITS_COMP_MSVC
|
||||
inline constexpr struct centimetre : si::centi_<si::metre> {} centimetre;
|
||||
#else
|
||||
inline constexpr struct centimetre : decltype(si::centi<si::metre>) {} centimetre;
|
||||
#endif
|
||||
inline constexpr struct gram : decltype(si::gram) {} gram;
|
||||
inline constexpr struct second : decltype(si::second) {} second;
|
||||
inline constexpr struct gal : named_unit<"Gal", centimetre / square(second)> {} gal;
|
||||
inline constexpr struct dyne : named_unit<"dyn", gram * centimetre / square(second)> {} dyne;
|
||||
inline constexpr struct erg : named_unit<"erg", dyne * centimetre> {} erg;
|
||||
inline constexpr struct barye : named_unit<"Ba", gram / (centimetre * square(second))> {} barye;
|
||||
inline constexpr struct poise : named_unit<"P", gram / (centimetre * second)> {} poise;
|
||||
inline constexpr struct stokes : named_unit<"St", square(centimetre) / second> {} stokes;
|
||||
inline constexpr struct kayser : named_unit<"K", one / centimetre> {} kayser;
|
||||
inline constexpr auto centimetre = si::centi<si::metre>;
|
||||
inline constexpr auto gram = si::gram;
|
||||
inline constexpr auto second = si::second;
|
||||
inline constexpr struct gal final : named_unit<"Gal", centimetre / square(second)> {} gal;
|
||||
inline constexpr struct dyne final : named_unit<"dyn", gram * centimetre / square(second)> {} dyne;
|
||||
inline constexpr struct erg final : named_unit<"erg", dyne * centimetre> {} erg;
|
||||
inline constexpr struct barye final : named_unit<"Ba", gram / (centimetre * square(second))> {} barye;
|
||||
inline constexpr struct poise final : named_unit<"P", gram / (centimetre * second)> {} poise;
|
||||
inline constexpr struct stokes final : named_unit<"St", square(centimetre) / second> {} stokes;
|
||||
inline constexpr struct kayser final : named_unit<"K", one / centimetre> {} kayser;
|
||||
// clang-format on
|
||||
|
||||
namespace unit_symbols {
|
||||
|
@ -49,15 +49,15 @@ using si::electronvolt;
|
||||
// effective cross-sectional area according to EU council directive 80/181/EEC
|
||||
// https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:01980L0181-20090527#page=10
|
||||
// https://www.fedlex.admin.ch/eli/cc/1994/3109_3109_3109/de
|
||||
inline constexpr struct barn : named_unit<"b", mag_power<10, -28> * square(si::metre)> {} barn;
|
||||
inline constexpr struct barn final : named_unit<"b", mag_power<10, -28> * square(si::metre)> {} barn;
|
||||
|
||||
// mass
|
||||
inline constexpr struct electron_mass : named_unit<"m_e", mag_ratio<9'109'383'701'528, 1'000'000'000'000> * mag_power<10, -31> * si::kilogram> {} electron_mass;
|
||||
inline constexpr struct proton_mass : named_unit<"m_p", mag_ratio<1'672'621'923'695, 1'000'000'000'000> * mag_power<10, -27> * si::kilogram> {} proton_mass;
|
||||
inline constexpr struct neutron_mass : named_unit<"m_n", mag_ratio<1'674'927'498'049, 1'000'000'000'000> * mag_power<10, -27> * si::kilogram> {} neutron_mass;
|
||||
inline constexpr struct electron_mass final : named_unit<"m_e", mag_ratio<9'109'383'701'528, 1'000'000'000'000> * mag_power<10, -31> * si::kilogram> {} electron_mass;
|
||||
inline constexpr struct proton_mass final : named_unit<"m_p", mag_ratio<1'672'621'923'695, 1'000'000'000'000> * mag_power<10, -27> * si::kilogram> {} proton_mass;
|
||||
inline constexpr struct neutron_mass final : named_unit<"m_n", mag_ratio<1'674'927'498'049, 1'000'000'000'000> * mag_power<10, -27> * si::kilogram> {} neutron_mass;
|
||||
|
||||
// speed
|
||||
inline constexpr struct speed_of_light : decltype(si::si2019::speed_of_light_in_vacuum) {} speed_of_light;
|
||||
inline constexpr auto speed_of_light = si::si2019::speed_of_light_in_vacuum;
|
||||
// clang-format on
|
||||
|
||||
namespace unit_symbols {
|
||||
|
@ -39,43 +39,43 @@ namespace mp_units::iau {
|
||||
|
||||
// clang-format off
|
||||
// time
|
||||
inline constexpr struct day : named_unit<"D", si::day> {} day;
|
||||
inline constexpr struct Julian_year : named_unit<"a", mag_ratio<365'25, 100> * day> {} Julian_year;
|
||||
inline constexpr struct day final : named_unit<"D", si::day> {} day;
|
||||
inline constexpr struct Julian_year final : named_unit<"a", mag_ratio<365'25, 100> * day> {} Julian_year;
|
||||
|
||||
// mass
|
||||
// https://en.wikipedia.org/wiki/Solar_mass
|
||||
// TODO What is the official mass of sun (every source in the Internet provides a different value)
|
||||
inline constexpr struct solar_mass : named_unit<symbol_text{u8"M_☉", "M_SUN"}, mag_ratio<198'847, 100'000> * mag_power<10, 30> * si::kilogram> {} solar_mass;
|
||||
inline constexpr struct Jupiter_mass : named_unit<"M_JUP", mag_ratio<1'898, 1'000> * mag_power<10, 27> * si::kilogram> {} Jupiter_mass;
|
||||
inline constexpr struct Earth_mass : named_unit<"M_EARTH", mag_ratio<59'742, 10'000> * mag_power<10, 24> * si::kilogram> {} Earth_mass;
|
||||
inline constexpr struct solar_mass final : named_unit<symbol_text{u8"M_☉", "M_SUN"}, mag_ratio<198'847, 100'000> * mag_power<10, 30> * si::kilogram> {} solar_mass;
|
||||
inline constexpr struct Jupiter_mass final : named_unit<"M_JUP", mag_ratio<1'898, 1'000> * mag_power<10, 27> * si::kilogram> {} Jupiter_mass;
|
||||
inline constexpr struct Earth_mass final : named_unit<"M_EARTH", mag_ratio<59'742, 10'000> * mag_power<10, 24> * si::kilogram> {} Earth_mass;
|
||||
|
||||
// length
|
||||
inline constexpr struct astronomical_unit : decltype(si::astronomical_unit) {} astronomical_unit;
|
||||
inline constexpr auto astronomical_unit = si::astronomical_unit;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Lunar_distance_(astronomy)
|
||||
inline constexpr struct lunar_distance : named_unit<"LD", mag<384'399> * si::kilo<si::metre>> {} lunar_distance;
|
||||
inline constexpr struct lunar_distance final : named_unit<"LD", mag<384'399> * si::kilo<si::metre>> {} lunar_distance;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Light-year
|
||||
inline constexpr struct light_year : named_unit<"ly", mag<9'460'730'472'580'800> * si::metre> {} light_year;
|
||||
inline constexpr struct light_year final : named_unit<"ly", mag<9'460'730'472'580'800> * si::metre> {} light_year;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Parsec
|
||||
inline constexpr struct parsec : named_unit<"pc", astronomical_unit / (mag_ratio<1, 3600> * si::degree)> {} parsec;
|
||||
inline constexpr struct parsec final : named_unit<"pc", astronomical_unit / (mag_ratio<1, 3600> * si::degree)> {} parsec;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Angstrom
|
||||
inline constexpr struct angstrom : named_unit<symbol_text{u8"Å", "A"}, mag_power<10, -10> * si::metre> {} angstrom;
|
||||
inline constexpr struct angstrom final : named_unit<symbol_text{u8"Å", "A"}, mag_power<10, -10> * si::metre> {} angstrom;
|
||||
|
||||
// selected constants
|
||||
// https://en.wikipedia.org/wiki/Astronomical_constant
|
||||
inline constexpr struct gaussian_gravitational_constant :
|
||||
inline constexpr struct gaussian_gravitational_constant final :
|
||||
named_unit<"k", mag_ratio<1'720'209'895, 100'000'000'000> * pow<3, 2>(astronomical_unit) / pow<1,2>(solar_mass) / day> {} gaussian_gravitational_constant;
|
||||
|
||||
inline constexpr struct speed_of_light :
|
||||
inline constexpr struct speed_of_light final :
|
||||
named_unit<symbol_text{u8"c₀", "c_0"}, si::si2019::speed_of_light_in_vacuum> {} speed_of_light;
|
||||
|
||||
inline constexpr struct constant_of_gravitation :
|
||||
inline constexpr struct constant_of_gravitation final :
|
||||
named_unit<"G", mag_ratio<667'430, 100'000> * mag_power<10, -11> * cubic(si::metre) / si::kilogram / square(si::second)> {} constant_of_gravitation;
|
||||
|
||||
inline constexpr struct hubble_constant :
|
||||
inline constexpr struct hubble_constant final :
|
||||
named_unit<symbol_text{u8"H₀", "H_0"}, mag_ratio<701, 10> * si::kilo<si::metre> / si::second / si::mega<parsec>> {} hubble_constant;
|
||||
// clang-format on
|
||||
|
||||
|
@ -31,14 +31,14 @@
|
||||
namespace mp_units::iec80000 {
|
||||
|
||||
// clang-format off
|
||||
template<PrefixableUnit U> struct kibi_ : prefixed_unit<"Ki", mag_power<2, 10>, U{}> {};
|
||||
template<PrefixableUnit U> struct mebi_ : prefixed_unit<"Mi", mag_power<2, 20>, U{}> {};
|
||||
template<PrefixableUnit U> struct gibi_ : prefixed_unit<"Gi", mag_power<2, 30>, U{}> {};
|
||||
template<PrefixableUnit U> struct tebi_ : prefixed_unit<"Ti", mag_power<2, 40>, U{}> {};
|
||||
template<PrefixableUnit U> struct pebi_ : prefixed_unit<"Pi", mag_power<2, 50>, U{}> {};
|
||||
template<PrefixableUnit U> struct exbi_ : prefixed_unit<"Ei", mag_power<2, 60>, U{}> {};
|
||||
template<PrefixableUnit U> struct zebi_ : prefixed_unit<"Zi", mag_power<2, 70>, U{}> {};
|
||||
template<PrefixableUnit U> struct yobi_ : prefixed_unit<"Yi", mag_power<2, 80>, U{}> {};
|
||||
template<PrefixableUnit U> struct kibi_ final : prefixed_unit<"Ki", mag_power<2, 10>, U{}> {};
|
||||
template<PrefixableUnit U> struct mebi_ final : prefixed_unit<"Mi", mag_power<2, 20>, U{}> {};
|
||||
template<PrefixableUnit U> struct gibi_ final : prefixed_unit<"Gi", mag_power<2, 30>, U{}> {};
|
||||
template<PrefixableUnit U> struct tebi_ final : prefixed_unit<"Ti", mag_power<2, 40>, U{}> {};
|
||||
template<PrefixableUnit U> struct pebi_ final : prefixed_unit<"Pi", mag_power<2, 50>, U{}> {};
|
||||
template<PrefixableUnit U> struct exbi_ final : prefixed_unit<"Ei", mag_power<2, 60>, U{}> {};
|
||||
template<PrefixableUnit U> struct zebi_ final : prefixed_unit<"Zi", mag_power<2, 70>, U{}> {};
|
||||
template<PrefixableUnit U> struct yobi_ final : prefixed_unit<"Yi", mag_power<2, 80>, U{}> {};
|
||||
|
||||
MP_UNITS_EXPORT_BEGIN
|
||||
|
||||
|
@ -36,7 +36,7 @@ namespace mp_units::iec80000 {
|
||||
|
||||
// dimensions of base quantities
|
||||
// clang-format off
|
||||
inline constexpr struct dim_traffic_intensity : base_dimension<"A"> {} dim_traffic_intensity;
|
||||
inline constexpr struct dim_traffic_intensity final : base_dimension<"A"> {} dim_traffic_intensity;
|
||||
// clang-format on
|
||||
|
||||
// quantities
|
||||
|
@ -34,11 +34,11 @@ MP_UNITS_EXPORT
|
||||
namespace mp_units::iec80000 {
|
||||
|
||||
// clang-format off
|
||||
inline constexpr struct erlang : named_unit<"E", kind_of<traffic_intensity>> {} erlang;
|
||||
inline constexpr struct bit : named_unit<"bit", one, kind_of<storage_capacity>> {} bit;
|
||||
inline constexpr struct octet : named_unit<"o", mag<8> * bit> {} octet;
|
||||
inline constexpr struct byte : named_unit<"B", mag<8> * bit> {} byte;
|
||||
inline constexpr struct baud : named_unit<"Bd", one / si::second, kind_of<modulation_rate>> {} baud;
|
||||
inline constexpr struct erlang final : named_unit<"E", kind_of<traffic_intensity>> {} erlang;
|
||||
inline constexpr struct bit final : named_unit<"bit", one, kind_of<storage_capacity>> {} bit;
|
||||
inline constexpr struct octet final : named_unit<"o", mag<8> * bit> {} octet;
|
||||
inline constexpr struct byte final : named_unit<"B", mag<8> * bit> {} byte;
|
||||
inline constexpr struct baud final : named_unit<"Bd", one / si::second, kind_of<modulation_rate>> {} baud;
|
||||
// clang-format on
|
||||
|
||||
} // namespace mp_units::iec80000
|
||||
|
@ -39,38 +39,38 @@ using namespace international;
|
||||
|
||||
// clang-format off
|
||||
// https://en.wikipedia.org/wiki/Imperial_units#Length
|
||||
inline constexpr struct hand : named_unit<"hh", mag_ratio<1, 3> * foot> {} hand;
|
||||
inline constexpr struct barleycorn : named_unit<"Bc", mag_ratio<1, 3> * inch> {} barleycorn;
|
||||
inline constexpr struct thou : named_unit<"th", mag_ratio<1, 12'000> * foot> {} thou;
|
||||
inline constexpr struct chain : named_unit<"ch", mag<22> * yard> {} chain;
|
||||
inline constexpr struct furlong : named_unit<"fur", mag<10> * chain> {} furlong;
|
||||
inline constexpr struct hand final : named_unit<"hh", mag_ratio<1, 3> * foot> {} hand;
|
||||
inline constexpr struct barleycorn final : named_unit<"Bc", mag_ratio<1, 3> * inch> {} barleycorn;
|
||||
inline constexpr struct thou final : named_unit<"th", mag_ratio<1, 12'000> * foot> {} thou;
|
||||
inline constexpr struct chain final : named_unit<"ch", mag<22> * yard> {} chain;
|
||||
inline constexpr struct furlong final : named_unit<"fur", mag<10> * chain> {} furlong;
|
||||
|
||||
// maritime units
|
||||
inline constexpr struct cable : named_unit<"cb", mag_ratio<1, 10> * nautical_mile> {} cable;
|
||||
inline constexpr struct fathom : named_unit<"ftm", mag_ratio<1, 1000> * nautical_mile> {} fathom;
|
||||
inline constexpr struct cable final : named_unit<"cb", mag_ratio<1, 10> * nautical_mile> {} cable;
|
||||
inline constexpr struct fathom final : named_unit<"ftm", mag_ratio<1, 1000> * nautical_mile> {} fathom;
|
||||
|
||||
// survey
|
||||
inline constexpr struct link : named_unit<"li", mag_ratio<1, 100> * chain> {} link;
|
||||
inline constexpr struct rod : named_unit<"rd", mag<25> * link> {} rod;
|
||||
inline constexpr struct link final : named_unit<"li", mag_ratio<1, 100> * chain> {} link;
|
||||
inline constexpr struct rod final : named_unit<"rd", mag<25> * link> {} rod;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Imperial_units#Area
|
||||
inline constexpr struct perch : decltype(square(rod)) {} perch;
|
||||
inline constexpr struct rood : decltype(mag<40> * perch) {} rood;
|
||||
inline constexpr struct acre : decltype(mag<4> * rood) {} acre;
|
||||
inline constexpr struct perch final : named_unit<"perch", square(rod)> {} perch;
|
||||
inline constexpr struct rood final : named_unit<"rood", mag<40> * perch> {} rood;
|
||||
inline constexpr struct acre final : named_unit<"acre", mag<4> * rood> {} acre;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Imperial_units#Volume
|
||||
inline constexpr struct gallon : named_unit<"gal", mag_ratio<454'609, 100'000> * si::litre> {} gallon;
|
||||
inline constexpr struct quart : named_unit<"qt", mag_ratio<1, 4> * gallon> {} quart;
|
||||
inline constexpr struct pint : named_unit<"pt", mag_ratio<1, 2> * quart> {} pint;
|
||||
inline constexpr struct gill : named_unit<"gi", mag_ratio<1, 4> * pint> {} gill;
|
||||
inline constexpr struct fluid_ounce : named_unit<"fl oz", mag_ratio<1, 5> * gill> {} fluid_ounce;
|
||||
inline constexpr struct gallon final : named_unit<"gal", mag_ratio<454'609, 100'000> * si::litre> {} gallon;
|
||||
inline constexpr struct quart final : named_unit<"qt", mag_ratio<1, 4> * gallon> {} quart;
|
||||
inline constexpr struct pint final : named_unit<"pt", mag_ratio<1, 2> * quart> {} pint;
|
||||
inline constexpr struct gill final : named_unit<"gi", mag_ratio<1, 4> * pint> {} gill;
|
||||
inline constexpr struct fluid_ounce final : named_unit<"fl oz", mag_ratio<1, 5> * gill> {} fluid_ounce;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Avoirdupois_system#Post-Elizabethan_units
|
||||
inline constexpr auto drachm = dram;
|
||||
inline constexpr struct stone : named_unit<"st", mag<14> * pound> {} stone;
|
||||
inline constexpr struct quarter : named_unit<"qr", mag<2> * stone> {} quarter;
|
||||
inline constexpr struct long_hundredweight : named_unit<"cwt", mag<8> * stone> {} long_hundredweight;
|
||||
inline constexpr struct ton : named_unit<"t", mag<2'240> * pound> {} ton;
|
||||
inline constexpr struct stone final : named_unit<"st", mag<14> * pound> {} stone;
|
||||
inline constexpr struct quarter final : named_unit<"qr", mag<2> * stone> {} quarter;
|
||||
inline constexpr struct long_hundredweight final : named_unit<"cwt", mag<8> * stone> {} long_hundredweight;
|
||||
inline constexpr struct ton final : named_unit<"t", mag<2'240> * pound> {} ton;
|
||||
inline constexpr auto long_ton = ton;
|
||||
// clang-format on
|
||||
|
||||
|
@ -37,48 +37,44 @@ namespace mp_units::international {
|
||||
|
||||
// clang-format off
|
||||
// mass
|
||||
inline constexpr struct pound : named_unit<"lb", mag_ratio<45'359'237, 100'000'000> * si::kilogram> {} pound;
|
||||
inline constexpr struct ounce : named_unit<"oz", mag_ratio<1, 16> * pound> {} ounce;
|
||||
inline constexpr struct dram : named_unit<"dr", mag_ratio<1, 16> * ounce> {} dram;
|
||||
inline constexpr struct grain : named_unit<"gr", mag_ratio<1, 7'000> * pound> {} grain;
|
||||
inline constexpr struct pound final : named_unit<"lb", mag_ratio<45'359'237, 100'000'000> * si::kilogram> {} pound;
|
||||
inline constexpr struct ounce final : named_unit<"oz", mag_ratio<1, 16> * pound> {} ounce;
|
||||
inline constexpr struct dram final : named_unit<"dr", mag_ratio<1, 16> * ounce> {} dram;
|
||||
inline constexpr struct grain final : named_unit<"gr", mag_ratio<1, 7'000> * pound> {} grain;
|
||||
|
||||
// length
|
||||
// https://en.wikipedia.org/wiki/United_States_customary_units#Length
|
||||
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 inch : named_unit<"in", mag_ratio<1, 12> * foot> {} inch;
|
||||
inline constexpr struct pica : named_unit<"P", mag_ratio<1, 6> * inch> {} pica;
|
||||
inline constexpr struct point : named_unit<"p", mag_ratio<1, 12> * pica> {} point;
|
||||
inline constexpr struct mil : named_unit<"mil", mag_ratio<1, 1'000> * inch> {} mil;
|
||||
inline constexpr struct twip : named_unit<"twip", mag_ratio<1, 20> * point> {} twip;
|
||||
inline constexpr struct mile : named_unit<"mi", mag<1760> * yard> {} mile;
|
||||
inline constexpr struct league : named_unit<"le", mag<3> * mile> {} league;
|
||||
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;
|
||||
inline constexpr struct inch final : named_unit<"in", mag_ratio<1, 12> * foot> {} inch;
|
||||
inline constexpr struct pica final : named_unit<"P", mag_ratio<1, 6> * inch> {} pica;
|
||||
inline constexpr struct point final : named_unit<"p", mag_ratio<1, 12> * pica> {} point;
|
||||
inline constexpr struct mil final : named_unit<"mil", mag_ratio<1, 1'000> * inch> {} mil;
|
||||
inline constexpr struct twip final : named_unit<"twip", mag_ratio<1, 20> * point> {} twip;
|
||||
inline constexpr struct mile final : named_unit<"mi", mag<1760> * yard> {} mile;
|
||||
inline constexpr struct league final : named_unit<"le", mag<3> * mile> {} league;
|
||||
|
||||
inline constexpr struct nautical_mile : named_unit<"nmi", mag<1852> * si::metre> {} nautical_mile;
|
||||
inline constexpr struct nautical_mile final : named_unit<"nmi", mag<1852> * si::metre> {} nautical_mile;
|
||||
|
||||
// speed
|
||||
inline constexpr struct knot : named_unit<"kn", nautical_mile / si::hour> {} knot;
|
||||
inline constexpr struct knot final : named_unit<"kn", nautical_mile / si::hour> {} knot;
|
||||
|
||||
// force
|
||||
// https://en.wikipedia.org/wiki/Poundal
|
||||
inline constexpr struct poundal : named_unit<"pdl", pound * foot / square(si::second)> {} poundal;
|
||||
inline constexpr struct poundal final : named_unit<"pdl", pound * foot / square(si::second)> {} poundal;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Pound_(force)
|
||||
inline constexpr struct pound_force : named_unit<"lbf", pound * si::standard_gravity> {} pound_force;
|
||||
inline constexpr struct pound_force final : named_unit<"lbf", pound * si::standard_gravity> {} pound_force;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Kip_(unit),
|
||||
#if MP_UNITS_COMP_MSVC
|
||||
inline constexpr struct kip : si::kilo_<pound_force> {} kip;
|
||||
#else
|
||||
inline constexpr struct kip : decltype(si::kilo<pound_force>) {} kip;
|
||||
#endif
|
||||
inline constexpr auto kip = si::kilo<pound_force>;
|
||||
|
||||
// pressure
|
||||
inline constexpr struct psi : named_unit<"psi", pound_force / square(inch)> {} psi;
|
||||
inline constexpr struct psi final : named_unit<"psi", pound_force / square(inch)> {} psi;
|
||||
|
||||
// power
|
||||
// https://en.wikipedia.org/wiki/Horsepower#Definitions
|
||||
inline constexpr struct mechanical_horsepower : named_unit<"hp(I)", mag<33'000> * foot * pound_force / si::minute> {} mechanical_horsepower;
|
||||
inline constexpr struct mechanical_horsepower final : named_unit<"hp(I)", mag<33'000> * foot * pound_force / si::minute> {} mechanical_horsepower;
|
||||
// clang-format on
|
||||
|
||||
|
||||
|
@ -35,13 +35,13 @@ namespace mp_units::isq {
|
||||
|
||||
// clang-format off
|
||||
// dimensions of base quantities
|
||||
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<symbol_text{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<symbol_text{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;
|
||||
// clang-format on
|
||||
|
||||
// base quantities
|
||||
|
@ -38,12 +38,8 @@ namespace mp_units::natural {
|
||||
|
||||
// clang-format off
|
||||
// units
|
||||
inline constexpr struct electronvolt : named_unit<"eV"> {} electronvolt;
|
||||
#if MP_UNITS_COMP_MSVC
|
||||
inline constexpr struct gigaelectronvolt : si::giga_<electronvolt> {} gigaelectronvolt;
|
||||
#else
|
||||
inline constexpr struct gigaelectronvolt : decltype(si::giga<electronvolt>) {} gigaelectronvolt;
|
||||
#endif
|
||||
inline constexpr struct electronvolt final : named_unit<"eV"> {} electronvolt;
|
||||
inline constexpr auto gigaelectronvolt = si::giga<electronvolt>;
|
||||
|
||||
// system references
|
||||
inline constexpr struct time : system_reference<isq::time, inverse(gigaelectronvolt)> {} time;
|
||||
|
@ -85,7 +85,7 @@ struct quantity_like_traits<std::chrono::duration<Rep, Period>> {
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct chrono_point_origin_ : absolute_point_origin<chrono_point_origin_<C>, isq::time> {
|
||||
struct chrono_point_origin_ final : absolute_point_origin<isq::time> {
|
||||
using clock = C;
|
||||
};
|
||||
MP_UNITS_EXPORT template<typename C>
|
||||
@ -113,12 +113,20 @@ struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::durati
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
[[nodiscard]] constexpr auto as_ratio(Magnitude auto m)
|
||||
requires(is_rational(m))
|
||||
{
|
||||
return std::ratio<get_value<std::intmax_t>(numerator(m)), get_value<std::intmax_t>(denominator(m))>{};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<QuantityOf<isq::time> Q>
|
||||
[[nodiscard]] constexpr auto to_chrono_duration(const Q& q)
|
||||
{
|
||||
constexpr auto canonical = get_canonical_unit(Q::unit);
|
||||
constexpr detail::ratio r = detail::as_ratio(canonical.mag);
|
||||
return std::chrono::duration<typename Q::rep, std::ratio<r.num, r.den>>{q};
|
||||
return std::chrono::duration<typename Q::rep, decltype(detail::as_ratio(get_canonical_unit(Q::unit).mag))>{q};
|
||||
}
|
||||
|
||||
template<QuantityPointOf<isq::time> QP>
|
||||
@ -127,9 +135,9 @@ template<QuantityPointOf<isq::time> QP>
|
||||
{
|
||||
using clock = MP_UNITS_TYPENAME decltype(QP::absolute_point_origin)::clock;
|
||||
using rep = MP_UNITS_TYPENAME QP::rep;
|
||||
constexpr auto canonical = get_canonical_unit(QP::unit);
|
||||
constexpr detail::ratio r = detail::as_ratio(canonical.mag);
|
||||
using ret_type = std::chrono::time_point<clock, std::chrono::duration<rep, std::ratio<r.num, r.den>>>;
|
||||
using ret_type =
|
||||
std::chrono::time_point<clock,
|
||||
std::chrono::duration<rep, decltype(detail::as_ratio(get_canonical_unit(QP::unit).mag))>>;
|
||||
return ret_type(to_chrono_duration(qp - qp.absolute_point_origin));
|
||||
}
|
||||
|
||||
|
@ -35,28 +35,28 @@ namespace mp_units::si {
|
||||
namespace si2019 {
|
||||
|
||||
// clang-format off
|
||||
inline constexpr struct hyperfine_structure_transition_frequency_of_cs :
|
||||
inline constexpr struct hyperfine_structure_transition_frequency_of_cs final :
|
||||
named_unit<symbol_text{u8"Δν_Cs", "dv_Cs"}, mag<9'192'631'770> * hertz> {} hyperfine_structure_transition_frequency_of_cs;
|
||||
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;
|
||||
inline constexpr struct planck_constant :
|
||||
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 :
|
||||
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 :
|
||||
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 :
|
||||
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 :
|
||||
inline constexpr struct luminous_efficacy final :
|
||||
named_unit<"K_cd", mag<683> * lumen / watt> {} luminous_efficacy;
|
||||
// clang-format on
|
||||
|
||||
} // namespace si2019
|
||||
|
||||
// clang-format off
|
||||
inline constexpr struct standard_gravity :
|
||||
inline constexpr struct standard_gravity final :
|
||||
named_unit<symbol_text{u8"g₀", "g_0"}, mag_ratio<980'665, 100'000> * metre / square(second)> {} standard_gravity;
|
||||
inline constexpr struct magnetic_constant :
|
||||
inline constexpr struct magnetic_constant final :
|
||||
named_unit<symbol_text{u8"μ₀", "u_0"}, mag<4> * mag_pi * mag_power<10, -7> * henry / metre> {} magnetic_constant;
|
||||
// clang-format on
|
||||
|
||||
|
@ -31,30 +31,30 @@
|
||||
namespace mp_units::si {
|
||||
|
||||
// clang-format off
|
||||
template<PrefixableUnit U> struct quecto_ : prefixed_unit<"q", mag_power<10, -30>, U{}> {};
|
||||
template<PrefixableUnit U> struct ronto_ : prefixed_unit<"r", mag_power<10, -27>, U{}> {};
|
||||
template<PrefixableUnit U> struct yocto_ : prefixed_unit<"y", mag_power<10, -24>, U{}> {};
|
||||
template<PrefixableUnit U> struct zepto_ : prefixed_unit<"z", mag_power<10, -21>, U{}> {};
|
||||
template<PrefixableUnit U> struct atto_ : prefixed_unit<"a", mag_power<10, -18>, U{}> {};
|
||||
template<PrefixableUnit U> struct femto_ : prefixed_unit<"f", mag_power<10, -15>, U{}> {};
|
||||
template<PrefixableUnit U> struct pico_ : prefixed_unit<"p", mag_power<10, -12>, U{}> {};
|
||||
template<PrefixableUnit U> struct nano_ : prefixed_unit<"n", mag_power<10, -9>, U{}> {};
|
||||
template<PrefixableUnit U> struct micro_ : prefixed_unit<symbol_text{u8"µ", "u"}, mag_power<10, -6>, U{}> {};
|
||||
template<PrefixableUnit U> struct milli_ : prefixed_unit<"m", mag_power<10, -3>, U{}> {};
|
||||
template<PrefixableUnit U> struct centi_ : prefixed_unit<"c", mag_power<10, -2>, U{}> {};
|
||||
template<PrefixableUnit U> struct deci_ : prefixed_unit<"d", mag_power<10, -1>, U{}> {};
|
||||
template<PrefixableUnit U> struct deca_ : prefixed_unit<"da", mag_power<10, 1>, U{}> {};
|
||||
template<PrefixableUnit U> struct hecto_ : prefixed_unit<"h", mag_power<10, 2>, U{}> {};
|
||||
template<PrefixableUnit U> struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U{}> {};
|
||||
template<PrefixableUnit U> struct mega_ : prefixed_unit<"M", mag_power<10, 6>, U{}> {};
|
||||
template<PrefixableUnit U> struct giga_ : prefixed_unit<"G", mag_power<10, 9>, U{}> {};
|
||||
template<PrefixableUnit U> struct tera_ : prefixed_unit<"T", mag_power<10, 12>, U{}> {};
|
||||
template<PrefixableUnit U> struct peta_ : prefixed_unit<"P", mag_power<10, 15>, U{}> {};
|
||||
template<PrefixableUnit U> struct exa_ : prefixed_unit<"E", mag_power<10, 18>, U{}> {};
|
||||
template<PrefixableUnit U> struct zetta_ : prefixed_unit<"Z", mag_power<10, 21>, U{}> {};
|
||||
template<PrefixableUnit U> struct yotta_ : prefixed_unit<"Y", mag_power<10, 24>, U{}> {};
|
||||
template<PrefixableUnit U> struct ronna_ : prefixed_unit<"R", mag_power<10, 27>, U{}> {};
|
||||
template<PrefixableUnit U> struct quetta_ : prefixed_unit<"Q", mag_power<10, 30>, U{}> {};
|
||||
template<PrefixableUnit U> struct quecto_ final : prefixed_unit<"q", mag_power<10, -30>, U{}> {};
|
||||
template<PrefixableUnit U> struct ronto_ final : prefixed_unit<"r", mag_power<10, -27>, U{}> {};
|
||||
template<PrefixableUnit U> struct yocto_ final : prefixed_unit<"y", mag_power<10, -24>, U{}> {};
|
||||
template<PrefixableUnit U> struct zepto_ final : prefixed_unit<"z", mag_power<10, -21>, U{}> {};
|
||||
template<PrefixableUnit U> struct atto_ final : prefixed_unit<"a", mag_power<10, -18>, U{}> {};
|
||||
template<PrefixableUnit U> struct femto_ final : prefixed_unit<"f", mag_power<10, -15>, U{}> {};
|
||||
template<PrefixableUnit U> struct pico_ final : prefixed_unit<"p", mag_power<10, -12>, U{}> {};
|
||||
template<PrefixableUnit U> struct nano_ final : prefixed_unit<"n", mag_power<10, -9>, U{}> {};
|
||||
template<PrefixableUnit U> struct micro_ final : prefixed_unit<symbol_text{u8"µ", "u"}, mag_power<10, -6>, U{}> {};
|
||||
template<PrefixableUnit U> struct milli_ final : prefixed_unit<"m", mag_power<10, -3>, U{}> {};
|
||||
template<PrefixableUnit U> struct centi_ final : prefixed_unit<"c", mag_power<10, -2>, U{}> {};
|
||||
template<PrefixableUnit U> struct deci_ final : prefixed_unit<"d", mag_power<10, -1>, U{}> {};
|
||||
template<PrefixableUnit U> struct deca_ final : prefixed_unit<"da", mag_power<10, 1>, U{}> {};
|
||||
template<PrefixableUnit U> struct hecto_ final : prefixed_unit<"h", mag_power<10, 2>, U{}> {};
|
||||
template<PrefixableUnit U> struct kilo_ final : prefixed_unit<"k", mag_power<10, 3>, U{}> {};
|
||||
template<PrefixableUnit U> struct mega_ final : prefixed_unit<"M", mag_power<10, 6>, U{}> {};
|
||||
template<PrefixableUnit U> struct giga_ final : prefixed_unit<"G", mag_power<10, 9>, U{}> {};
|
||||
template<PrefixableUnit U> struct tera_ final : prefixed_unit<"T", mag_power<10, 12>, U{}> {};
|
||||
template<PrefixableUnit U> struct peta_ final : prefixed_unit<"P", mag_power<10, 15>, U{}> {};
|
||||
template<PrefixableUnit U> struct exa_ final : prefixed_unit<"E", mag_power<10, 18>, U{}> {};
|
||||
template<PrefixableUnit U> struct zetta_ final : prefixed_unit<"Z", mag_power<10, 21>, U{}> {};
|
||||
template<PrefixableUnit U> struct yotta_ final : prefixed_unit<"Y", mag_power<10, 24>, U{}> {};
|
||||
template<PrefixableUnit U> struct ronna_ final : prefixed_unit<"R", mag_power<10, 27>, U{}> {};
|
||||
template<PrefixableUnit U> struct quetta_ final : prefixed_unit<"Q", mag_power<10, 30>, U{}> {};
|
||||
|
||||
MP_UNITS_EXPORT_BEGIN
|
||||
|
||||
|
@ -38,59 +38,55 @@ namespace si {
|
||||
|
||||
// clang-format off
|
||||
// base units
|
||||
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;
|
||||
#if MP_UNITS_COMP_MSVC
|
||||
inline constexpr struct kilogram : kilo_<gram> {} kilogram;
|
||||
#else
|
||||
inline constexpr struct kilogram : decltype(kilo<gram>) {} kilogram;
|
||||
#endif
|
||||
inline constexpr struct ampere : named_unit<"A", kind_of<isq::electric_current>> {} ampere;
|
||||
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 ampere final : named_unit<"A", kind_of<isq::electric_current>> {} ampere;
|
||||
|
||||
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 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 mole : named_unit<"mol", kind_of<isq::amount_of_substance>> {} mole;
|
||||
inline constexpr struct candela : named_unit<"cd", kind_of<isq::luminous_intensity>> {} candela;
|
||||
inline constexpr struct mole final : named_unit<"mol", kind_of<isq::amount_of_substance>> {} mole;
|
||||
inline constexpr struct candela final : named_unit<"cd", kind_of<isq::luminous_intensity>> {} candela;
|
||||
|
||||
// derived named units
|
||||
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 hertz : named_unit<"Hz", one / second, kind_of<isq::frequency>> {} hertz;
|
||||
inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
||||
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 hertz final : named_unit<"Hz", one / second, kind_of<isq::frequency>> {} hertz;
|
||||
inline constexpr struct newton final : named_unit<"N", kilogram * metre / square(second)> {} newton;
|
||||
#ifdef pascal
|
||||
#pragma push_macro("pascal")
|
||||
#undef pascal
|
||||
#define MP_UNITS_REDEFINE_PASCAL
|
||||
#endif
|
||||
inline constexpr struct pascal : named_unit<"Pa", newton / square(metre)> {} pascal;
|
||||
inline constexpr struct pascal final : named_unit<"Pa", newton / square(metre)> {} pascal;
|
||||
#ifdef MP_UNITS_REDEFINE_PASCAL
|
||||
#pragma pop_macro("pascal")
|
||||
#undef MP_UNITS_REDEFINE_PASCAL
|
||||
#endif
|
||||
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<symbol_text{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
||||
inline constexpr struct siemens : named_unit<"S", one / ohm> {} siemens;
|
||||
inline constexpr struct weber : named_unit<"Wb", volt * second> {} weber;
|
||||
inline constexpr struct tesla : named_unit<"T", weber / square(metre)> {} tesla;
|
||||
inline constexpr struct henry : named_unit<"H", weber / ampere> {} henry;
|
||||
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<symbol_text{u8"Ω", "ohm"}, volt / ampere> {} ohm;
|
||||
inline constexpr struct siemens final : named_unit<"S", one / ohm> {} siemens;
|
||||
inline constexpr struct weber final : named_unit<"Wb", volt * second> {} weber;
|
||||
inline constexpr struct tesla final : named_unit<"T", weber / square(metre)> {} tesla;
|
||||
inline constexpr struct henry final : named_unit<"H", weber / ampere> {} henry;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
inline constexpr struct lumen : named_unit<"lm", candela * steradian> {} lumen;
|
||||
inline constexpr struct lux : named_unit<"lx", lumen / square(metre)> {} lux;
|
||||
inline constexpr struct becquerel : named_unit<"Bq", one / second, kind_of<isq::activity>> {} becquerel;
|
||||
inline constexpr struct gray : named_unit<"Gy", joule / kilogram, kind_of<isq::absorbed_dose>> {} gray;
|
||||
inline constexpr struct sievert : named_unit<"Sv", joule / kilogram, kind_of<isq::dose_equivalent>> {} sievert;
|
||||
inline constexpr struct katal : named_unit<"kat", mole / second> {} katal;
|
||||
inline constexpr struct lumen final : named_unit<"lm", candela * steradian> {} lumen;
|
||||
inline constexpr struct lux final : named_unit<"lx", lumen / square(metre)> {} lux;
|
||||
inline constexpr struct becquerel final : named_unit<"Bq", one / second, kind_of<isq::activity>> {} becquerel;
|
||||
inline constexpr struct gray final : named_unit<"Gy", joule / kilogram, kind_of<isq::absorbed_dose>> {} gray;
|
||||
inline constexpr struct sievert final : named_unit<"Sv", joule / kilogram, kind_of<isq::dose_equivalent>> {} sievert;
|
||||
inline constexpr struct katal final : named_unit<"kat", mole / second> {} katal;
|
||||
// clang-format on
|
||||
|
||||
} // namespace si
|
||||
@ -99,24 +95,20 @@ namespace non_si {
|
||||
|
||||
// clang-format off
|
||||
// non-SI units accepted for use with the SI
|
||||
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 day : named_unit<"d", mag<24> * hour> {} day;
|
||||
inline constexpr struct astronomical_unit : named_unit<"au", mag<149'597'870'700> * si::metre> {} astronomical_unit;
|
||||
inline constexpr struct degree : named_unit<symbol_text{u8"°", "deg"}, mag_pi / mag<180> * si::radian> {} degree;
|
||||
inline constexpr struct arcminute : named_unit<symbol_text{u8"′", "'"}, mag_ratio<1, 60> * degree> {} arcminute;
|
||||
inline constexpr struct arcsecond : named_unit<symbol_text{u8"″", "''"}, mag_ratio<1, 60> * arcminute> {} arcsecond;
|
||||
inline constexpr struct are : named_unit<"a", square(si::deca<si::metre>)> {} are;
|
||||
#if MP_UNITS_COMP_MSVC
|
||||
inline constexpr struct hectare : si::hecto_<are> {} hectare;
|
||||
#else
|
||||
inline constexpr struct hectare : decltype(si::hecto<are>) {} hectare;
|
||||
#endif
|
||||
inline constexpr struct litre : named_unit<"l", cubic(si::deci<si::metre>)> {} litre;
|
||||
inline constexpr struct tonne : named_unit<"t", mag<1000> * si::kilogram> {} tonne;
|
||||
inline constexpr struct dalton : named_unit<"Da", mag_ratio<16'605'390'666'050, 10'000'000'000'000> * mag_power<10, -27> * si::kilogram> {} dalton;
|
||||
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 day final : named_unit<"d", mag<24> * hour> {} day;
|
||||
inline constexpr struct astronomical_unit final : named_unit<"au", mag<149'597'870'700> * si::metre> {} astronomical_unit;
|
||||
inline constexpr struct degree final : named_unit<symbol_text{u8"°", "deg"}, mag_pi / mag<180> * si::radian> {} degree;
|
||||
inline constexpr struct arcminute final : named_unit<symbol_text{u8"′", "'"}, mag_ratio<1, 60> * degree> {} arcminute;
|
||||
inline constexpr struct arcsecond final : named_unit<symbol_text{u8"″", "''"}, mag_ratio<1, 60> * arcminute> {} arcsecond;
|
||||
inline constexpr struct are final : named_unit<"a", square(si::deca<si::metre>)> {} are;
|
||||
inline constexpr auto hectare = si::hecto<are>;
|
||||
inline constexpr struct litre final : named_unit<"l", cubic(si::deci<si::metre>)> {} litre;
|
||||
inline constexpr struct tonne final : named_unit<"t", mag<1000> * si::kilogram> {} tonne;
|
||||
inline constexpr struct dalton final : named_unit<"Da", mag_ratio<16'605'390'666'050, 10'000'000'000'000> * mag_power<10, -27> * si::kilogram> {} dalton;
|
||||
// TODO A different value is provided in the SI Brochure and different in the ISO 80000
|
||||
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 electronvolt final : named_unit<"eV", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * si::joule> {} electronvolt;
|
||||
// TODO the below are logarithmic units - how to support those?
|
||||
// neper
|
||||
// bel
|
||||
|
@ -36,11 +36,11 @@ namespace mp_units::typographic {
|
||||
|
||||
// clang-format off
|
||||
// https://en.wikipedia.org/wiki/Point_(typography)
|
||||
inline constexpr struct pica_us : named_unit<"pica(us)", mag_ratio<166'044, 1'000'000> * international::inch> {} pica_us;
|
||||
inline constexpr struct point_us : named_unit<"point(us)", mag_ratio<1, 12> * pica_us> {} point_us;
|
||||
inline constexpr struct pica_us final : named_unit<"pica(us)", mag_ratio<166'044, 1'000'000> * international::inch> {} pica_us;
|
||||
inline constexpr struct point_us final : named_unit<"point(us)", mag_ratio<1, 12> * pica_us> {} point_us;
|
||||
|
||||
inline constexpr struct point_dtp : named_unit<"point(dtp)", mag_ratio<1, 72> * international::inch> {} point_dtp;
|
||||
inline constexpr struct pica_dtp : named_unit<"pica(dtp)", mag<12> * point_dtp> {} pica_dtp;
|
||||
inline constexpr struct point_dtp final : named_unit<"point(dtp)", mag_ratio<1, 72> * international::inch> {} point_dtp;
|
||||
inline constexpr struct pica_dtp final : named_unit<"pica(dtp)", mag<12> * point_dtp> {} pica_dtp;
|
||||
// clang-format on
|
||||
|
||||
} // namespace mp_units::typographic
|
||||
|
@ -41,12 +41,12 @@ using namespace international;
|
||||
|
||||
// https://en.wikipedia.org/wiki/United_States_customary_units#Length
|
||||
// nautical
|
||||
inline constexpr struct fathom : named_unit<"ftm(us)", mag<2> * yard> {} fathom;
|
||||
inline constexpr struct cable : named_unit<"cb(us)", mag<120> * fathom> {} cable;
|
||||
inline constexpr struct fathom final : named_unit<"ftm(us)", mag<2> * yard> {} fathom;
|
||||
inline constexpr struct cable final : named_unit<"cb(us)", mag<120> * fathom> {} cable;
|
||||
|
||||
// survey
|
||||
struct us_survey_foot : named_unit<"ft(us)", mag_ratio<1'200, 3'937> * si::metre> {};
|
||||
struct us_survey_mile : named_unit<"mi(us)", mag<5280> * us_survey_foot{}> {};
|
||||
struct us_survey_foot final : named_unit<"ft(us)", mag_ratio<1'200, 3'937> * si::metre> {};
|
||||
struct us_survey_mile final : named_unit<"mi(us)", mag<5280> * us_survey_foot{}> {};
|
||||
|
||||
[[deprecated("In accordance with NIST SP 811, as of January 1, 2023, the use of the U.S. survey foot and U.S. survey mile is deprecated.")]]
|
||||
inline constexpr us_survey_foot us_survey_foot;
|
||||
@ -54,72 +54,72 @@ inline constexpr us_survey_foot us_survey_foot;
|
||||
[[deprecated("In accordance with NIST SP 811, as of January 1, 2023, the use of the U.S. survey foot and U.S. survey mile is deprecated.")]]
|
||||
inline constexpr us_survey_mile us_survey_mile;
|
||||
|
||||
inline constexpr struct link : named_unit<"li", mag_ratio<33, 50> * foot> {} link;
|
||||
inline constexpr struct rod : named_unit<"rd", mag<25> * link> {} rod;
|
||||
inline constexpr struct chain : named_unit<"ch", mag<4> * rod> {} chain;
|
||||
inline constexpr struct furlong : named_unit<"fur", mag<10> * chain> {} furlong;
|
||||
inline constexpr struct link final : named_unit<"li", mag_ratio<33, 50> * foot> {} link;
|
||||
inline constexpr struct rod final : named_unit<"rd", mag<25> * link> {} rod;
|
||||
inline constexpr struct chain final : named_unit<"ch", mag<4> * rod> {} chain;
|
||||
inline constexpr struct furlong final : named_unit<"fur", mag<10> * chain> {} furlong;
|
||||
// clang-format on
|
||||
|
||||
namespace survey1893 {
|
||||
|
||||
// clang-format off
|
||||
inline constexpr struct us_survey_foot : named_unit<"ft(us)", mag_ratio<1'200, 3'937> * si::metre> {} us_survey_foot;
|
||||
inline constexpr struct link : named_unit<"li", mag_ratio<33, 50> * us_survey_foot> {} link;
|
||||
inline constexpr struct rod : named_unit<"rd", mag<25> * link> {} rod;
|
||||
inline constexpr struct chain : named_unit<"ch", mag<4> * rod> {} chain;
|
||||
inline constexpr struct furlong : named_unit<"fur", mag<10> * chain> {} furlong;
|
||||
inline constexpr struct us_survey_mile : named_unit<"mi(us)", mag<8> * furlong> {} us_survey_mile;
|
||||
inline constexpr struct league : named_unit<"lea", mag<3> * us_survey_mile> {} league;
|
||||
inline constexpr struct us_survey_foot final : named_unit<"ft(us)", mag_ratio<1'200, 3'937> * si::metre> {} us_survey_foot;
|
||||
inline constexpr struct link final : named_unit<"li", mag_ratio<33, 50> * us_survey_foot> {} link;
|
||||
inline constexpr struct rod final : named_unit<"rd", mag<25> * link> {} rod;
|
||||
inline constexpr struct chain final : named_unit<"ch", mag<4> * rod> {} chain;
|
||||
inline constexpr struct furlong final : named_unit<"fur", mag<10> * chain> {} furlong;
|
||||
inline constexpr struct us_survey_mile final : named_unit<"mi(us)", mag<8> * furlong> {} us_survey_mile;
|
||||
inline constexpr struct league final : named_unit<"lea", mag<3> * us_survey_mile> {} league;
|
||||
// clang-format on
|
||||
|
||||
} // namespace survey1893
|
||||
|
||||
// clang-format off
|
||||
// https://en.wikipedia.org/wiki/United_States_customary_units#Area
|
||||
inline constexpr struct acre : named_unit<"acre", mag<10> * square(survey1893::chain)> {} acre;
|
||||
inline constexpr struct section : named_unit<"section", mag<640> * acre> {} section;
|
||||
inline constexpr struct acre final : named_unit<"acre", mag<10> * square(survey1893::chain)> {} acre;
|
||||
inline constexpr struct section final : named_unit<"section", mag<640> * acre> {} section;
|
||||
|
||||
// https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume
|
||||
inline constexpr struct gallon : named_unit<"gal", mag<231> * cubic(inch)> {} gallon;
|
||||
inline constexpr struct pottle : named_unit<"pot", mag_ratio<1, 2> * gallon> {} pottle;
|
||||
inline constexpr struct quart : named_unit<"qt", mag_ratio<1, 2> * pottle> {} quart;
|
||||
inline constexpr struct pint : named_unit<"pt", mag_ratio<1, 2> * quart> {} pint;
|
||||
inline constexpr struct cup : named_unit<"c", mag_ratio<1, 2> * pint> {} cup;
|
||||
inline constexpr struct gill : named_unit<"gi", mag_ratio<1, 2> * cup> {} gill;
|
||||
inline constexpr struct fluid_ounce : named_unit<"fl oz", mag_ratio<1, 4> * gill> {} fluid_ounce;
|
||||
inline constexpr struct tablespoon : named_unit<"tbsp", mag_ratio<1, 2> * fluid_ounce> {} tablespoon;
|
||||
inline constexpr struct shot : named_unit<"jig", mag<3> * tablespoon> {} shot;
|
||||
inline constexpr struct teaspoon : named_unit<"tsp", mag_ratio<1, 3> * tablespoon> {} teaspoon;
|
||||
inline constexpr struct minim : named_unit<"min", mag_ratio<1, 80> * teaspoon> {} minim;
|
||||
inline constexpr struct fluid_dram : named_unit<"fl dr", mag<60> * minim> {} fluid_dram;
|
||||
inline constexpr struct barrel : named_unit<"bbl", mag_ratio<315, 10> * gallon> {} barrel;
|
||||
inline constexpr struct oil_barrel : named_unit<"bbl", mag_ratio<4, 3> * barrel> {} oil_barrel;
|
||||
inline constexpr struct hogshead : decltype(mag<63> * gallon) {} hogshead;
|
||||
inline constexpr struct gallon final : named_unit<"gal", mag<231> * cubic(inch)> {} gallon;
|
||||
inline constexpr struct pottle final : named_unit<"pot", mag_ratio<1, 2> * gallon> {} pottle;
|
||||
inline constexpr struct quart final : named_unit<"qt", mag_ratio<1, 2> * pottle> {} quart;
|
||||
inline constexpr struct pint final : named_unit<"pt", mag_ratio<1, 2> * quart> {} pint;
|
||||
inline constexpr struct cup final : named_unit<"c", mag_ratio<1, 2> * pint> {} cup;
|
||||
inline constexpr struct gill final : named_unit<"gi", mag_ratio<1, 2> * cup> {} gill;
|
||||
inline constexpr struct fluid_ounce final : named_unit<"fl oz", mag_ratio<1, 4> * gill> {} fluid_ounce;
|
||||
inline constexpr struct tablespoon final : named_unit<"tbsp", mag_ratio<1, 2> * fluid_ounce> {} tablespoon;
|
||||
inline constexpr struct shot final : named_unit<"jig", mag<3> * tablespoon> {} shot;
|
||||
inline constexpr struct teaspoon final : named_unit<"tsp", mag_ratio<1, 3> * tablespoon> {} teaspoon;
|
||||
inline constexpr struct minim final : named_unit<"min", mag_ratio<1, 80> * teaspoon> {} minim;
|
||||
inline constexpr struct fluid_dram final : named_unit<"fl dr", mag<60> * minim> {} fluid_dram;
|
||||
inline constexpr struct barrel final : named_unit<"bbl", mag_ratio<315, 10> * gallon> {} barrel;
|
||||
inline constexpr struct oil_barrel final : named_unit<"bbl", mag_ratio<4, 3> * barrel> {} oil_barrel;
|
||||
inline constexpr struct hogshead final : named_unit<"hogshead", mag<63> * gallon> {} hogshead;
|
||||
|
||||
// https://en.wikipedia.org/wiki/United_States_customary_units#Dry_volume
|
||||
inline constexpr struct dry_barrel : named_unit<"bbl", mag<7056> * cubic(inch)> {} dry_barrel;
|
||||
inline constexpr struct bushel : named_unit<"bu", mag_ratio<3'523'907'016'688, 100'000'000'000> * si::litre> {} bushel;
|
||||
inline constexpr struct peck : named_unit<"pk", mag_ratio<1, 4> * bushel> {} peck;
|
||||
inline constexpr struct dry_gallon : named_unit<"gal", mag_ratio<1, 2> * peck> {} dry_gallon;
|
||||
inline constexpr struct dry_quart : named_unit<"qt", mag_ratio<1, 4> * dry_gallon> {} dry_quart;
|
||||
inline constexpr struct dry_pint : named_unit<"pt", mag_ratio<1, 2> * dry_quart> {} dry_pint;
|
||||
inline constexpr struct dry_barrel final : named_unit<"bbl", mag<7056> * cubic(inch)> {} dry_barrel;
|
||||
inline constexpr struct bushel final : named_unit<"bu", mag_ratio<3'523'907'016'688, 100'000'000'000> * si::litre> {} bushel;
|
||||
inline constexpr struct peck final : named_unit<"pk", mag_ratio<1, 4> * bushel> {} peck;
|
||||
inline constexpr struct dry_gallon final : named_unit<"gal", mag_ratio<1, 2> * peck> {} dry_gallon;
|
||||
inline constexpr struct dry_quart final : named_unit<"qt", mag_ratio<1, 4> * dry_gallon> {} dry_quart;
|
||||
inline constexpr struct dry_pint final : named_unit<"pt", mag_ratio<1, 2> * dry_quart> {} dry_pint;
|
||||
|
||||
// https://en.wikipedia.org/wiki/United_States_customary_units#Mass_and_Weight
|
||||
// https://en.wikipedia.org/wiki/Avoirdupois_system#American_customary_system
|
||||
inline constexpr struct quarter : named_unit<"qr", mag<25> * pound> {} quarter;
|
||||
inline constexpr struct short_hundredweight : named_unit<"cwt", mag<100> * pound> {} short_hundredweight;
|
||||
inline constexpr struct ton : named_unit<"t", mag<2'000> * pound> {} ton;
|
||||
inline constexpr struct quarter final : named_unit<"qr", mag<25> * pound> {} quarter;
|
||||
inline constexpr struct short_hundredweight final : named_unit<"cwt", mag<100> * pound> {} short_hundredweight;
|
||||
inline constexpr struct ton final : named_unit<"t", mag<2'000> * pound> {} ton;
|
||||
inline constexpr auto short_ton = ton;
|
||||
inline constexpr struct pennyweight : named_unit<"dwt", mag<24> * grain> {} pennyweight;
|
||||
inline constexpr struct troy_once : named_unit<"oz t", mag<20> * pennyweight> {} troy_once;
|
||||
inline constexpr struct troy_pound : named_unit<"lb t", mag<12> * troy_once> {} troy_pound;
|
||||
inline constexpr struct pennyweight final : named_unit<"dwt", mag<24> * grain> {} pennyweight;
|
||||
inline constexpr struct troy_once final : named_unit<"oz t", mag<20> * pennyweight> {} troy_once;
|
||||
inline constexpr struct troy_pound final : named_unit<"lb t", mag<12> * troy_once> {} troy_pound;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Inch_of_mercury
|
||||
inline constexpr struct inch_of_mercury : named_unit<"inHg", mag_ratio<3'386'389, 1'000> * si::pascal> {} inch_of_mercury;
|
||||
inline constexpr struct inch_of_mercury final : named_unit<"inHg", mag_ratio<3'386'389, 1'000> * si::pascal> {} inch_of_mercury;
|
||||
|
||||
// https://en.wikipedia.org/wiki/United_States_customary_units#Temperature
|
||||
inline constexpr struct zeroth_degree_Fahrenheit : relative_point_origin<quantity_point{-32 * (mag_ratio<5, 9> * si::degree_Celsius)}> {} zeroth_degree_Fahrenheit;
|
||||
inline constexpr struct degree_Fahrenheit : named_unit<symbol_text{u8"°F", "`F"}, mag_ratio<5, 9> * si::degree_Celsius, zeroth_degree_Fahrenheit> {} 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;
|
||||
inline constexpr struct degree_Fahrenheit final : named_unit<symbol_text{u8"°F", "`F"}, mag_ratio<5, 9> * si::degree_Celsius, zeroth_degree_Fahrenheit> {} degree_Fahrenheit;
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
@ -1,3 +1,25 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
module;
|
||||
|
||||
#include <mp-units/bits/core_gmf.h>
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <catch2/matchers/catch_matchers_templated.hpp>
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <algorithm>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
import mp_units;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_exception.hpp>
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <catch2/matchers/catch_matchers.hpp>
|
||||
#include <catch2/matchers/catch_matchers_exception.hpp>
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <mp-units/compat_macros.h>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <matrix>
|
||||
#include <ostream>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <catch2/catch_template_test_macros.hpp>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers.hpp>
|
||||
#include <mp-units/ext/format.h>
|
||||
#include <limits>
|
||||
#include <numbers>
|
||||
#ifdef MP_UNITS_MODULES
|
||||
@ -37,7 +38,7 @@ using namespace mp_units;
|
||||
using namespace mp_units::angular;
|
||||
using namespace mp_units::angular::unit_symbols;
|
||||
|
||||
inline constexpr struct half_revolution : named_unit<"hrev", mag_pi * radian> {
|
||||
inline constexpr struct half_revolution final : named_unit<"hrev", mag_pi * radian> {
|
||||
} half_revolution;
|
||||
inline constexpr auto hrev = half_revolution;
|
||||
|
||||
|
@ -40,12 +40,12 @@ namespace {
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
inline constexpr struct my_origin : absolute_point_origin<my_origin, isq::length> {
|
||||
inline constexpr struct my_origin final : absolute_point_origin<isq::length> {
|
||||
} my_origin;
|
||||
inline constexpr struct my_relative_origin : relative_point_origin<my_origin + isq::length(42 * si::metre)> {
|
||||
inline constexpr struct my_relative_origin final : relative_point_origin<my_origin + isq::length(42 * si::metre)> {
|
||||
} my_relative_origin;
|
||||
|
||||
struct dim_speed : decltype(isq::dim_length / isq::dim_time) {};
|
||||
inline constexpr auto dim_speed = isq::dim_length / isq::dim_time;
|
||||
|
||||
// BaseDimension
|
||||
static_assert(detail::BaseDimension<struct isq::dim_length>);
|
||||
@ -53,7 +53,7 @@ static_assert(!detail::BaseDimension<decltype(isq::dim_length / isq::dim_time)>)
|
||||
static_assert(!detail::BaseDimension<decltype(inverse(isq::dim_time))>);
|
||||
static_assert(!detail::BaseDimension<decltype(pow<2>(isq::dim_length))>);
|
||||
static_assert(!detail::BaseDimension<derived_dimension<struct isq::dim_length, per<struct isq::dim_time>>>);
|
||||
static_assert(!detail::BaseDimension<dim_speed>);
|
||||
static_assert(!detail::BaseDimension<std::remove_const_t<decltype(dim_speed)>>);
|
||||
static_assert(!detail::BaseDimension<base_dimension<"L">>);
|
||||
static_assert(!detail::BaseDimension<struct si::metre>);
|
||||
static_assert(!detail::BaseDimension<int>);
|
||||
@ -64,7 +64,7 @@ static_assert(detail::DerivedDimension<decltype(inverse(isq::dim_time))>);
|
||||
static_assert(detail::DerivedDimension<decltype(pow<2>(isq::dim_length))>);
|
||||
static_assert(detail::DerivedDimension<derived_dimension<struct isq::dim_length, per<struct isq::dim_time>>>);
|
||||
static_assert(detail::DerivedDimension<struct dimension_one>);
|
||||
static_assert(!detail::DerivedDimension<dim_speed>);
|
||||
static_assert(detail::DerivedDimension<std::remove_const_t<decltype(dim_speed)>>);
|
||||
static_assert(!detail::DerivedDimension<struct isq::dim_length>);
|
||||
static_assert(!detail::DerivedDimension<struct si::metre>);
|
||||
static_assert(!detail::DerivedDimension<int>);
|
||||
@ -76,7 +76,7 @@ static_assert(Dimension<decltype(inverse(isq::dim_time))>);
|
||||
static_assert(Dimension<decltype(pow<2>(isq::dim_length))>);
|
||||
static_assert(Dimension<derived_dimension<struct isq::dim_length, per<struct isq::dim_time>>>);
|
||||
static_assert(Dimension<struct dimension_one>);
|
||||
static_assert(!Dimension<dim_speed>);
|
||||
static_assert(Dimension<std::remove_const_t<decltype(dim_speed)>>);
|
||||
static_assert(!Dimension<base_dimension<"L">>);
|
||||
static_assert(!Dimension<struct si::metre>);
|
||||
static_assert(!Dimension<int>);
|
||||
@ -85,7 +85,7 @@ static_assert(!Dimension<int>);
|
||||
// TODO add tests
|
||||
|
||||
// QuantitySpec
|
||||
struct speed : decltype(isq::length / isq::time) {}; // this is not recommended
|
||||
inline constexpr auto speed = isq::length / isq::time;
|
||||
|
||||
static_assert(QuantitySpec<struct isq::length>);
|
||||
static_assert(QuantitySpec<struct isq::radius>);
|
||||
@ -94,7 +94,7 @@ static_assert(QuantitySpec<decltype(kind_of<isq::length>)>);
|
||||
static_assert(QuantitySpec<decltype(isq::length / isq::time)>);
|
||||
static_assert(QuantitySpec<decltype(pow<2>(isq::length))>);
|
||||
static_assert(QuantitySpec<struct dimensionless>);
|
||||
static_assert(!QuantitySpec<speed>);
|
||||
static_assert(QuantitySpec<std::remove_const_t<decltype(speed)>>);
|
||||
static_assert(!QuantitySpec<struct isq::dim_length>);
|
||||
static_assert(!QuantitySpec<int>);
|
||||
|
||||
@ -106,21 +106,21 @@ static_assert(!detail::NamedQuantitySpec<std::remove_const_t<decltype(kind_of<is
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(isq::length / isq::time)>);
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(pow<2>(isq::length))>);
|
||||
static_assert(detail::NamedQuantitySpec<struct dimensionless>);
|
||||
static_assert(!detail::NamedQuantitySpec<speed>);
|
||||
static_assert(!detail::NamedQuantitySpec<std::remove_const_t<decltype(speed)>>);
|
||||
static_assert(!detail::NamedQuantitySpec<struct isq::dim_length>);
|
||||
static_assert(!detail::NamedQuantitySpec<int>);
|
||||
|
||||
// IntermediateDerivedQuantitySpec
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<struct isq::length>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<struct isq::radius>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<decltype(kind_of<isq::length>)>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<struct isq::speed>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(isq::length / isq::time)>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(pow<2>(isq::length))>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<struct dimensionless>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<speed>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<struct isq::dim_length>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<int>);
|
||||
// DerivedQuantitySpec
|
||||
static_assert(!detail::DerivedQuantitySpec<struct isq::length>);
|
||||
static_assert(!detail::DerivedQuantitySpec<struct isq::radius>);
|
||||
static_assert(!detail::DerivedQuantitySpec<decltype(kind_of<isq::length>)>);
|
||||
static_assert(!detail::DerivedQuantitySpec<struct isq::speed>);
|
||||
static_assert(detail::DerivedQuantitySpec<decltype(isq::length / isq::time)>);
|
||||
static_assert(detail::DerivedQuantitySpec<decltype(pow<2>(isq::length))>);
|
||||
static_assert(!detail::DerivedQuantitySpec<struct dimensionless>);
|
||||
static_assert(detail::DerivedQuantitySpec<std::remove_const_t<decltype(speed)>>);
|
||||
static_assert(!detail::DerivedQuantitySpec<struct isq::dim_length>);
|
||||
static_assert(!detail::DerivedQuantitySpec<int>);
|
||||
|
||||
// QuantityKindSpec
|
||||
static_assert(!detail::QuantityKindSpec<struct isq::length>);
|
||||
@ -130,7 +130,7 @@ static_assert(!detail::QuantityKindSpec<struct isq::speed>);
|
||||
static_assert(!detail::QuantityKindSpec<decltype(isq::length / isq::time)>);
|
||||
static_assert(!detail::QuantityKindSpec<decltype(pow<2>(isq::length))>);
|
||||
static_assert(!detail::QuantityKindSpec<struct dimensionless>);
|
||||
static_assert(!detail::QuantityKindSpec<speed>);
|
||||
static_assert(!detail::QuantityKindSpec<std::remove_const_t<decltype(speed)>>);
|
||||
static_assert(!detail::QuantityKindSpec<struct isq::dim_length>);
|
||||
static_assert(!detail::QuantityKindSpec<int>);
|
||||
|
||||
@ -138,10 +138,8 @@ static_assert(!detail::QuantityKindSpec<int>);
|
||||
// TODO add tests
|
||||
|
||||
// Unit
|
||||
struct metre_per_second : decltype(si::metre / si::second) {};
|
||||
|
||||
static_assert(Unit<struct si::metre>);
|
||||
static_assert(Unit<struct si::kilogram>);
|
||||
static_assert(Unit<decltype(si::kilogram)>);
|
||||
static_assert(Unit<decltype(si::kilo<si::gram>)>);
|
||||
static_assert(Unit<struct natural::electronvolt>);
|
||||
static_assert(Unit<decltype(si::metre / si::second)>);
|
||||
@ -151,13 +149,12 @@ static_assert(Unit<decltype(square(si::metre))>);
|
||||
static_assert(Unit<decltype(pow<2>(si::metre))>);
|
||||
static_assert(Unit<struct si::standard_gravity>);
|
||||
static_assert(Unit<scaled_unit<mag<10>, struct si::second>>);
|
||||
static_assert(Unit<metre_per_second>);
|
||||
static_assert(Unit<derived_unit<struct si::metre, per<struct si::second>>>);
|
||||
static_assert(Unit<struct one>);
|
||||
static_assert(!Unit<named_unit<"?", isq::length>>);
|
||||
static_assert(!Unit<named_unit<"?", kind_of<isq::length>>>);
|
||||
static_assert(!Unit<named_unit<"?">>);
|
||||
static_assert(!Unit<named_unit<"?", si::metre / si::second>>);
|
||||
static_assert(!Unit<named_unit<"?", si::metre, isq::length>>);
|
||||
static_assert(!Unit<named_unit<"?", si::metre, kind_of<isq::length>>>);
|
||||
static_assert(!Unit<prefixed_unit<"?", mag<10>, si::second>>);
|
||||
static_assert(!Unit<struct isq::dim_length>);
|
||||
static_assert(!Unit<int>);
|
||||
@ -168,7 +165,7 @@ static_assert(!Unit<std::chrono::seconds>);
|
||||
// NamedUnit
|
||||
static_assert(detail::NamedUnit<struct si::metre>);
|
||||
static_assert(detail::NamedUnit<struct natural::electronvolt>);
|
||||
static_assert(!detail::NamedUnit<struct si::kilogram>);
|
||||
static_assert(!detail::NamedUnit<decltype(si::kilogram)>);
|
||||
static_assert(!detail::NamedUnit<decltype(si::kilo<si::gram>)>);
|
||||
static_assert(!detail::NamedUnit<decltype(si::metre / si::second)>);
|
||||
static_assert(!detail::NamedUnit<decltype(inverse(si::second))>);
|
||||
@ -177,13 +174,12 @@ static_assert(!detail::NamedUnit<decltype(square(si::metre))>);
|
||||
static_assert(!detail::NamedUnit<decltype(pow<2>(si::metre))>);
|
||||
static_assert(detail::NamedUnit<struct si::standard_gravity>);
|
||||
static_assert(!detail::NamedUnit<scaled_unit<mag<10>, struct si::second>>);
|
||||
static_assert(!detail::NamedUnit<metre_per_second>);
|
||||
static_assert(!detail::NamedUnit<derived_unit<struct si::metre, per<struct si::second>>>);
|
||||
static_assert(!detail::NamedUnit<struct one>);
|
||||
static_assert(!detail::NamedUnit<named_unit<"?", isq::length>>);
|
||||
static_assert(!detail::NamedUnit<named_unit<"?", kind_of<isq::length>>>);
|
||||
static_assert(!detail::NamedUnit<named_unit<"?">>);
|
||||
static_assert(!detail::NamedUnit<named_unit<"?", si::metre / si::second>>);
|
||||
static_assert(!detail::NamedUnit<named_unit<"?", si::metre, isq::length>>);
|
||||
static_assert(!detail::NamedUnit<named_unit<"?", si::metre, kind_of<isq::length>>>);
|
||||
static_assert(!detail::NamedUnit<prefixed_unit<"?", mag<10>, si::second>>);
|
||||
static_assert(!detail::NamedUnit<struct isq::dim_length>);
|
||||
static_assert(!detail::NamedUnit<int>);
|
||||
@ -194,7 +190,7 @@ static_assert(!detail::NamedUnit<std::chrono::seconds>);
|
||||
// PrefixableUnit
|
||||
static_assert(PrefixableUnit<struct si::metre>);
|
||||
static_assert(PrefixableUnit<struct natural::electronvolt>);
|
||||
static_assert(!PrefixableUnit<struct si::kilogram>);
|
||||
static_assert(!PrefixableUnit<decltype(si::kilogram)>);
|
||||
static_assert(!PrefixableUnit<decltype(si::kilo<si::gram>)>);
|
||||
static_assert(!PrefixableUnit<decltype(si::metre / si::second)>);
|
||||
static_assert(!PrefixableUnit<decltype(inverse(si::second))>);
|
||||
@ -203,13 +199,12 @@ static_assert(!PrefixableUnit<decltype(square(si::metre))>);
|
||||
static_assert(!PrefixableUnit<decltype(pow<2>(si::metre))>);
|
||||
static_assert(PrefixableUnit<struct si::standard_gravity>);
|
||||
static_assert(!PrefixableUnit<scaled_unit<mag<10>, struct si::second>>);
|
||||
static_assert(!PrefixableUnit<metre_per_second>);
|
||||
static_assert(!PrefixableUnit<derived_unit<struct si::metre, per<struct si::second>>>);
|
||||
static_assert(!PrefixableUnit<struct one>);
|
||||
static_assert(!PrefixableUnit<named_unit<"?", isq::length>>);
|
||||
static_assert(!PrefixableUnit<named_unit<"?", kind_of<isq::length>>>);
|
||||
static_assert(!PrefixableUnit<named_unit<"?">>);
|
||||
static_assert(!PrefixableUnit<named_unit<"?", si::metre / si::second>>);
|
||||
static_assert(!PrefixableUnit<named_unit<"?", si::metre, isq::length>>);
|
||||
static_assert(!PrefixableUnit<named_unit<"?", si::metre, kind_of<isq::length>>>);
|
||||
static_assert(!PrefixableUnit<prefixed_unit<"?", mag<10>, si::second>>);
|
||||
static_assert(!PrefixableUnit<struct isq::dim_length>);
|
||||
static_assert(!PrefixableUnit<int>);
|
||||
@ -220,7 +215,7 @@ static_assert(!PrefixableUnit<std::chrono::seconds>);
|
||||
// AssociatedUnit
|
||||
static_assert(AssociatedUnit<struct si::metre>);
|
||||
static_assert(!AssociatedUnit<struct natural::electronvolt>);
|
||||
static_assert(AssociatedUnit<struct si::kilogram>);
|
||||
static_assert(AssociatedUnit<decltype(si::kilogram)>);
|
||||
static_assert(AssociatedUnit<decltype(si::kilo<si::gram>)>);
|
||||
static_assert(AssociatedUnit<decltype(si::metre / si::second)>);
|
||||
static_assert(AssociatedUnit<decltype(inverse(si::second))>);
|
||||
@ -229,13 +224,12 @@ static_assert(AssociatedUnit<decltype(square(si::metre))>);
|
||||
static_assert(AssociatedUnit<decltype(pow<2>(si::metre))>);
|
||||
static_assert(AssociatedUnit<struct si::standard_gravity>);
|
||||
static_assert(AssociatedUnit<scaled_unit<mag<10>, struct si::second>>);
|
||||
static_assert(AssociatedUnit<metre_per_second>);
|
||||
static_assert(AssociatedUnit<derived_unit<struct si::metre, per<struct si::second>>>);
|
||||
static_assert(AssociatedUnit<struct one>);
|
||||
static_assert(!AssociatedUnit<named_unit<"?", isq::length>>);
|
||||
static_assert(!AssociatedUnit<named_unit<"?", kind_of<isq::length>>>);
|
||||
static_assert(!AssociatedUnit<named_unit<"?">>);
|
||||
static_assert(!AssociatedUnit<named_unit<"?", si::metre / si::second>>);
|
||||
static_assert(!AssociatedUnit<named_unit<"?", si::metre, isq::length>>);
|
||||
static_assert(!AssociatedUnit<named_unit<"?", si::metre, kind_of<isq::length>>>);
|
||||
static_assert(!AssociatedUnit<prefixed_unit<"?", mag<10>, si::second>>);
|
||||
static_assert(!AssociatedUnit<struct isq::dim_length>);
|
||||
static_assert(!AssociatedUnit<int>);
|
||||
@ -246,7 +240,7 @@ static_assert(!AssociatedUnit<std::chrono::seconds>);
|
||||
// UnitOf
|
||||
static_assert(UnitOf<struct si::metre, isq::length>);
|
||||
static_assert(UnitOf<struct si::metre, isq::radius>);
|
||||
static_assert(UnitOf<struct si::kilogram, isq::mass>);
|
||||
static_assert(UnitOf<decltype(si::kilogram), isq::mass>);
|
||||
static_assert(UnitOf<struct si::hertz, isq::frequency>);
|
||||
static_assert(UnitOf<struct si::hertz, inverse(isq::time)>);
|
||||
static_assert(UnitOf<struct one, dimensionless>);
|
||||
@ -366,7 +360,7 @@ static_assert(QuantityPoint<quantity_point<isq::length[si::metre], my_relative_o
|
||||
static_assert(QuantityPoint<quantity_point<isq::radius[si::metre], my_origin>>);
|
||||
static_assert(QuantityPoint<quantity_point<isq::radius[si::metre], my_relative_origin>>);
|
||||
static_assert(!QuantityPoint<decltype(isq::length[si::metre])>);
|
||||
static_assert(!QuantityPoint<absolute_point_origin<struct my_origin, isq::length>>);
|
||||
static_assert(!QuantityPoint<absolute_point_origin<isq::length>>);
|
||||
static_assert(!QuantityPoint<struct my_origin>);
|
||||
static_assert(!QuantityPoint<struct my_relative_origin>);
|
||||
#if MP_UNITS_HOSTED
|
||||
@ -400,7 +394,7 @@ static_assert(QuantityPointOf<quantity_point<isq::radius[si::metre], my_relative
|
||||
// PointOrigin
|
||||
static_assert(PointOrigin<struct my_origin>);
|
||||
static_assert(PointOrigin<struct my_relative_origin>);
|
||||
static_assert(!PointOrigin<absolute_point_origin<struct my_origin, isq::length>>);
|
||||
static_assert(!PointOrigin<absolute_point_origin<isq::length>>);
|
||||
static_assert(!PointOrigin<relative_point_origin<my_origin + 42 * si::metre>>);
|
||||
static_assert(!PointOrigin<quantity_point<si::metre, my_origin>>);
|
||||
static_assert(!PointOrigin<quantity_point<isq::length[si::metre], my_origin>>);
|
||||
|
@ -32,15 +32,15 @@ using namespace mp_units;
|
||||
using dimension_one_ = struct dimension_one;
|
||||
|
||||
// clang-format off
|
||||
inline constexpr struct length_ : base_dimension<"L"> {} length;
|
||||
inline constexpr struct mass_ : base_dimension<"M"> {} mass;
|
||||
inline constexpr struct time_ : base_dimension<"T"> {} time;
|
||||
inline constexpr struct length_ final : base_dimension<"L"> {} length;
|
||||
inline constexpr struct mass_ final : base_dimension<"M"> {} mass;
|
||||
inline constexpr struct time_ final : base_dimension<"T"> {} time;
|
||||
|
||||
inline constexpr struct my_length1_ : decltype(length) {} my_length1;
|
||||
inline constexpr struct my_length2_ : decltype(length) {} my_length2;
|
||||
inline constexpr auto my_length1 = length;
|
||||
inline constexpr auto my_length2 = length;
|
||||
|
||||
QUANTITY_SPEC_(q_time, time);
|
||||
inline constexpr struct second_ : named_unit<"s", kind_of<q_time>> {} second;
|
||||
inline constexpr struct second_ final : named_unit<"s", kind_of<q_time>> {} second;
|
||||
|
||||
inline constexpr auto frequency = inverse(time);
|
||||
inline constexpr auto action = inverse(time);
|
||||
|
@ -46,40 +46,38 @@ using namespace std::chrono_literals;
|
||||
using sys_seconds = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
|
||||
#endif
|
||||
|
||||
inline constexpr struct zeroth_length : absolute_point_origin<zeroth_length, isq::length> {
|
||||
inline constexpr struct zeroth_length final : absolute_point_origin<isq::length> {
|
||||
} zeroth_length;
|
||||
|
||||
inline constexpr struct mean_sea_level : absolute_point_origin<mean_sea_level, isq::height> {
|
||||
inline constexpr struct mean_sea_level final : absolute_point_origin<isq::height> {
|
||||
} mean_sea_level;
|
||||
|
||||
inline constexpr struct my_mean_sea_level : decltype(mean_sea_level) {
|
||||
} my_mean_sea_level;
|
||||
inline constexpr auto my_mean_sea_level = mean_sea_level;
|
||||
|
||||
inline constexpr struct same_mean_sea_level : relative_point_origin<mean_sea_level + 0 * isq::height[m]> {
|
||||
inline constexpr struct same_mean_sea_level final : relative_point_origin<mean_sea_level + 0 * isq::height[m]> {
|
||||
} same_mean_sea_level;
|
||||
|
||||
inline constexpr struct ground_level : relative_point_origin<mean_sea_level + 42 * isq::height[m]> {
|
||||
inline constexpr struct ground_level final : relative_point_origin<mean_sea_level + 42 * isq::height[m]> {
|
||||
} ground_level;
|
||||
|
||||
inline constexpr struct my_ground_level : decltype(ground_level) {
|
||||
} my_ground_level;
|
||||
inline constexpr auto my_ground_level = ground_level;
|
||||
|
||||
inline constexpr struct same_ground_level1 : relative_point_origin<mean_sea_level + 42 * isq::height[m]> {
|
||||
inline constexpr struct same_ground_level1 final : relative_point_origin<mean_sea_level + 42 * isq::height[m]> {
|
||||
} same_ground_level1;
|
||||
|
||||
inline constexpr struct same_ground_level2 : relative_point_origin<my_mean_sea_level + 42 * isq::height[m]> {
|
||||
inline constexpr struct same_ground_level2 final : relative_point_origin<my_mean_sea_level + 42 * isq::height[m]> {
|
||||
} same_ground_level2;
|
||||
|
||||
inline constexpr struct tower_peak : relative_point_origin<ground_level + 42 * isq::height[m]> {
|
||||
inline constexpr struct tower_peak final : relative_point_origin<ground_level + 42 * isq::height[m]> {
|
||||
} tower_peak;
|
||||
|
||||
inline constexpr struct other_ground_level : relative_point_origin<mean_sea_level + 123 * isq::height[m]> {
|
||||
inline constexpr struct other_ground_level final : relative_point_origin<mean_sea_level + 123 * isq::height[m]> {
|
||||
} other_ground_level;
|
||||
|
||||
inline constexpr struct other_absolute_level : absolute_point_origin<other_absolute_level, isq::height> {
|
||||
inline constexpr struct other_absolute_level final : absolute_point_origin<isq::height> {
|
||||
} other_absolute_level;
|
||||
|
||||
inline constexpr struct zero : absolute_point_origin<zero, dimensionless> {
|
||||
inline constexpr struct zero final : absolute_point_origin<dimensionless> {
|
||||
} zero;
|
||||
|
||||
QUANTITY_SPEC(special_height, isq::height);
|
||||
@ -107,12 +105,12 @@ static_assert(my_mean_sea_level != other_absolute_level);
|
||||
static_assert(ground_level != other_ground_level);
|
||||
|
||||
template<auto QS>
|
||||
struct absolute_po_ : absolute_point_origin<absolute_po_<QS>, QS> {};
|
||||
struct absolute_po_ final : absolute_point_origin<QS> {};
|
||||
template<auto QS>
|
||||
inline constexpr absolute_po_<QS> absolute_po;
|
||||
|
||||
template<auto QP>
|
||||
struct relative_po_ : relative_point_origin<QP> {};
|
||||
struct relative_po_ final : relative_point_origin<QP> {};
|
||||
template<auto QP>
|
||||
inline constexpr relative_po_<QP> relative_po;
|
||||
|
||||
@ -120,7 +118,7 @@ static_assert(relative_po<absolute_po<isq::length> + isq::height(42 * m)>.quanti
|
||||
static_assert(relative_po<absolute_po<kind_of<isq::length>> + isq::height(42 * m)>.quantity_spec == isq::height);
|
||||
static_assert(relative_po<absolute_po<isq::height> + 42 * m>.quantity_spec == isq::height);
|
||||
|
||||
inline constexpr struct my_kelvin : named_unit<"my_K", mag<10> * si::kelvin> {
|
||||
inline constexpr struct my_kelvin final : named_unit<"my_K", mag<10> * si::kelvin> {
|
||||
} my_kelvin;
|
||||
|
||||
static_assert(default_point_origin(si::kelvin) == si::absolute_zero);
|
||||
@ -311,7 +309,7 @@ static_assert(quantity_point<si::degree_Celsius, si::ice_point>::dimension == is
|
||||
static_assert(quantity_point<si::degree_Celsius, si::ice_point>::unit == si::degree_Celsius);
|
||||
static_assert(is_of_type<quantity_point<si::degree_Celsius, si::ice_point>::point_origin, struct si::ice_point>);
|
||||
static_assert(
|
||||
is_of_type<quantity_point<si::degree_Celsius, si::ice_point>::absolute_point_origin, struct si::zeroth_kelvin>);
|
||||
is_of_type<quantity_point<si::degree_Celsius, si::ice_point>::absolute_point_origin, struct si::absolute_zero>);
|
||||
|
||||
static_assert(quantity_point<isq::Celsius_temperature[si::degree_Celsius], si::ice_point>::reference ==
|
||||
isq::Celsius_temperature[si::degree_Celsius]);
|
||||
@ -324,7 +322,7 @@ static_assert(is_of_type<quantity_point<isq::Celsius_temperature[si::degree_Cels
|
||||
struct si::ice_point>);
|
||||
static_assert(
|
||||
is_of_type<quantity_point<isq::Celsius_temperature[si::degree_Celsius], si::ice_point>::absolute_point_origin,
|
||||
struct si::zeroth_kelvin>);
|
||||
struct si::absolute_zero>);
|
||||
|
||||
|
||||
//////////////////
|
||||
@ -892,10 +890,10 @@ static_assert(quantity_point{isq::height(123 * m)}.unit == si::metre);
|
||||
static_assert(quantity_point{isq::height(123 * m)}.quantity_spec == isq::height);
|
||||
|
||||
static_assert(std::is_same_v<decltype(quantity_point{20 * deg_C})::rep, int>);
|
||||
static_assert(std::is_same_v<std::remove_const_t<decltype(quantity_point{20 * deg_C}.point_origin)>,
|
||||
struct si::zeroth_degree_Celsius>);
|
||||
static_assert(
|
||||
std::is_same_v<std::remove_const_t<decltype(quantity_point{20 * deg_C}.point_origin)>, struct si::ice_point>);
|
||||
static_assert(std::is_same_v<std::remove_const_t<decltype(quantity_point{20 * deg_C}.absolute_point_origin)>,
|
||||
struct si::zeroth_kelvin>);
|
||||
struct si::absolute_zero>);
|
||||
static_assert(quantity_point{20 * deg_C}.unit == si::degree_Celsius);
|
||||
static_assert(quantity_point{20 * deg_C}.quantity_spec == kind_of<isq::thermodynamic_temperature>);
|
||||
|
||||
@ -1493,7 +1491,7 @@ static_assert(ground_level - other_ground_level == -81 * m);
|
||||
static_assert(other_ground_level - tower_peak == 39 * m);
|
||||
static_assert(tower_peak - other_ground_level == -39 * m);
|
||||
|
||||
inline constexpr struct zero_m_per_s : absolute_point_origin<zero_m_per_s, kind_of<isq::speed>> {
|
||||
inline constexpr struct zero_m_per_s final : absolute_point_origin<kind_of<isq::speed>> {
|
||||
} zero_m_per_s;
|
||||
|
||||
// commutativity and associativity
|
||||
@ -1581,7 +1579,7 @@ static_assert(
|
||||
is_of_type<quantity_point{10 * isq::height[m] / (2 * isq::time[s])} + (10 * isq::height[m] / (2 * isq::time[s])),
|
||||
quantity_point<(isq::height / isq::time)[m / s], zeroth_point_origin<isq::height / isq::time>, int>>);
|
||||
|
||||
inline constexpr struct zero_Hz : absolute_point_origin<zero_Hz, kind_of<isq::frequency>> {
|
||||
inline constexpr struct zero_Hz final : absolute_point_origin<kind_of<isq::frequency>> {
|
||||
} zero_Hz;
|
||||
|
||||
static_assert(((zero_Hz + 10 / (2 * isq::period_duration[s])) + 5 * isq::frequency[Hz]).quantity_from(zero_Hz) ==
|
||||
@ -1665,7 +1663,7 @@ consteval bool invalid_subtraction(Ts... ts)
|
||||
return !requires { (... - ts); };
|
||||
}
|
||||
|
||||
inline constexpr struct zero_Bq : absolute_point_origin<zero_Bq, kind_of<isq::activity>> {
|
||||
inline constexpr struct zero_Bq final : absolute_point_origin<kind_of<isq::activity>> {
|
||||
} zero_Bq;
|
||||
|
||||
static_assert(invalid_addition(zero_Bq + 5 * isq::activity[Bq], 5 * isq::frequency[Hz]));
|
||||
|
@ -33,16 +33,16 @@ using dimensionless_ = struct dimensionless;
|
||||
using dim_one_ = struct dimension_one;
|
||||
|
||||
// clang-format off
|
||||
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_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;
|
||||
|
||||
// quantities specification
|
||||
QUANTITY_SPEC_(length, dim_length);
|
||||
QUANTITY_SPEC_(mass, dim_mass);
|
||||
QUANTITY_SPEC_(time, dim_time);
|
||||
|
||||
inline constexpr struct second_ : named_unit<"s", kind_of<time>> {} second;
|
||||
inline constexpr struct second_ final : named_unit<"s", kind_of<time>> {} second;
|
||||
|
||||
QUANTITY_SPEC_(height, length);
|
||||
QUANTITY_SPEC_(width, length);
|
||||
@ -88,98 +88,98 @@ QUANTITY_SPEC_(kinetic_energy, mechanical_energy, mass* pow<2>(speed));
|
||||
// concepts verification
|
||||
static_assert(QuantitySpec<length_>);
|
||||
static_assert(detail::NamedQuantitySpec<length_>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<length_>);
|
||||
static_assert(!detail::DerivedQuantitySpec<length_>);
|
||||
static_assert(!detail::QuantityKindSpec<length_>);
|
||||
|
||||
static_assert(QuantitySpec<frequency_>);
|
||||
static_assert(detail::NamedQuantitySpec<frequency_>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<frequency_>);
|
||||
static_assert(!detail::DerivedQuantitySpec<frequency_>);
|
||||
static_assert(!detail::QuantityKindSpec<frequency_>);
|
||||
|
||||
static_assert(QuantitySpec<decltype(inverse(time))>);
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(inverse(time))>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(inverse(time))>);
|
||||
static_assert(detail::DerivedQuantitySpec<decltype(inverse(time))>);
|
||||
static_assert(!detail::QuantityKindSpec<decltype(inverse(time))>);
|
||||
|
||||
static_assert(QuantitySpec<dimensionless_>);
|
||||
static_assert(detail::NamedQuantitySpec<dimensionless_>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<dimensionless_>);
|
||||
static_assert(!detail::DerivedQuantitySpec<dimensionless_>);
|
||||
static_assert(!detail::QuantityKindSpec<dimensionless_>);
|
||||
|
||||
static_assert(QuantitySpec<kind_of_<length_>>);
|
||||
static_assert(!detail::NamedQuantitySpec<kind_of_<length_>>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<kind_of_<length_>>);
|
||||
static_assert(!detail::DerivedQuantitySpec<kind_of_<length_>>);
|
||||
static_assert(detail::QuantityKindSpec<kind_of_<length_>>);
|
||||
|
||||
static_assert(QuantitySpec<frequency_>);
|
||||
static_assert(detail::NamedQuantitySpec<frequency_>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<frequency_>);
|
||||
static_assert(!detail::DerivedQuantitySpec<frequency_>);
|
||||
static_assert(!detail::QuantityKindSpec<frequency_>);
|
||||
|
||||
static_assert(QuantitySpec<decltype(inverse(time))>);
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(inverse(time))>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(inverse(time))>);
|
||||
static_assert(detail::DerivedQuantitySpec<decltype(inverse(time))>);
|
||||
static_assert(!detail::QuantityKindSpec<decltype(inverse(time))>);
|
||||
|
||||
static_assert(QuantitySpec<kind_of_<decltype(length / time)>>);
|
||||
static_assert(!detail::NamedQuantitySpec<kind_of_<decltype(length / time)>>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<kind_of_<decltype(length / time)>>);
|
||||
static_assert(detail::DerivedQuantitySpec<kind_of_<decltype(length / time)>>);
|
||||
static_assert(detail::QuantityKindSpec<kind_of_<decltype(length / time)>>);
|
||||
|
||||
static_assert(QuantitySpec<decltype(kind_of<length> / kind_of<time>)>);
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(kind_of<length> / kind_of<time>)>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(kind_of<length> / kind_of<time>)>);
|
||||
static_assert(detail::DerivedQuantitySpec<decltype(kind_of<length> / kind_of<time>)>);
|
||||
static_assert(detail::QuantityKindSpec<decltype(kind_of<length> / kind_of<time>)>);
|
||||
|
||||
static_assert(QuantitySpec<decltype(kind_of<length> * kind_of<time>)>);
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(kind_of<length> * kind_of<time>)>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(kind_of<length> * kind_of<time>)>);
|
||||
static_assert(detail::DerivedQuantitySpec<decltype(kind_of<length> * kind_of<time>)>);
|
||||
static_assert(detail::QuantityKindSpec<decltype(kind_of<length> * kind_of<time>)>);
|
||||
|
||||
// dimensionless
|
||||
static_assert(QuantitySpec<dimensionless_>);
|
||||
static_assert(detail::NamedQuantitySpec<dimensionless_>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<dimensionless_>);
|
||||
static_assert(!detail::DerivedQuantitySpec<dimensionless_>);
|
||||
static_assert(!detail::QuantityKindSpec<dimensionless_>);
|
||||
|
||||
static_assert(QuantitySpec<decltype(length / length)>);
|
||||
static_assert(detail::NamedQuantitySpec<decltype(length / length)>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<decltype(length / length)>);
|
||||
static_assert(!detail::DerivedQuantitySpec<decltype(length / length)>);
|
||||
static_assert(!detail::QuantityKindSpec<decltype(length / length)>);
|
||||
|
||||
static_assert(QuantitySpec<decltype(width / length)>);
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(width / length)>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(width / length)>);
|
||||
static_assert(detail::DerivedQuantitySpec<decltype(width / length)>);
|
||||
static_assert(!detail::QuantityKindSpec<decltype(width / length)>);
|
||||
|
||||
static_assert(QuantitySpec<decltype(kind_of<length> / kind_of<length>)>);
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(kind_of<length> / kind_of<length>)>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<decltype(kind_of<length> / kind_of<length>)>);
|
||||
static_assert(!detail::DerivedQuantitySpec<decltype(kind_of<length> / kind_of<length>)>);
|
||||
static_assert(detail::QuantityKindSpec<decltype(kind_of<length> / kind_of<length>)>);
|
||||
|
||||
static_assert(QuantitySpec<decltype(kind_of<length> / length)>);
|
||||
static_assert(detail::NamedQuantitySpec<decltype(kind_of<length> / length)>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<decltype(kind_of<length> / length)>);
|
||||
static_assert(!detail::DerivedQuantitySpec<decltype(kind_of<length> / length)>);
|
||||
static_assert(!detail::QuantityKindSpec<decltype(kind_of<length> / length)>);
|
||||
|
||||
static_assert(QuantitySpec<decltype(length / kind_of<length>)>);
|
||||
static_assert(detail::NamedQuantitySpec<decltype(length / kind_of<length>)>);
|
||||
static_assert(!detail::IntermediateDerivedQuantitySpec<decltype(length / kind_of<length>)>);
|
||||
static_assert(!detail::DerivedQuantitySpec<decltype(length / kind_of<length>)>);
|
||||
static_assert(!detail::QuantityKindSpec<decltype(length / kind_of<length>)>);
|
||||
|
||||
static_assert(QuantitySpec<decltype(width / kind_of<length>)>);
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(width / kind_of<length>)>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(width / kind_of<length>)>);
|
||||
static_assert(detail::DerivedQuantitySpec<decltype(width / kind_of<length>)>);
|
||||
static_assert(!detail::QuantityKindSpec<decltype(width / kind_of<length>)>);
|
||||
|
||||
// length
|
||||
static_assert(QuantitySpec<decltype(speed * time)>);
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(speed * time)>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(speed * time)>);
|
||||
static_assert(detail::DerivedQuantitySpec<decltype(speed * time)>);
|
||||
|
||||
// derived QuantitySpec expression template syntax verification
|
||||
static_assert(!detail::NamedQuantitySpec<decltype(speed * time)>);
|
||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(speed * time)>);
|
||||
static_assert(detail::DerivedQuantitySpec<decltype(speed * time)>);
|
||||
|
||||
static_assert(is_of_type<dimensionless * time, time_>);
|
||||
static_assert(is_of_type<time * dimensionless, time_>);
|
||||
|
@ -35,9 +35,9 @@ using one_ = struct one;
|
||||
|
||||
// base dimensions
|
||||
// clang-format off
|
||||
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_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;
|
||||
|
||||
// quantities specification
|
||||
QUANTITY_SPEC_(length, dim_length);
|
||||
@ -60,16 +60,16 @@ QUANTITY_SPEC_(power, force* speed);
|
||||
QUANTITY_SPEC_(storage_capacity, dimensionless, is_kind);
|
||||
|
||||
// base units
|
||||
inline constexpr struct second_ : named_unit<"s", kind_of<time>> {} second;
|
||||
inline constexpr struct metre_ : named_unit<"m", kind_of<length>> {} metre;
|
||||
inline constexpr struct gram_ : named_unit<"g", kind_of<mass>> {} gram;
|
||||
inline constexpr struct kilogram_ : decltype(si::kilo<gram>) {} kilogram;
|
||||
inline constexpr struct second_ final : named_unit<"s", kind_of<time>> {} second;
|
||||
inline constexpr struct metre_ final : named_unit<"m", kind_of<length>> {} metre;
|
||||
inline constexpr struct gram_ final : named_unit<"g", kind_of<mass>> {} gram;
|
||||
inline constexpr auto kilogram = si::kilo<gram>;
|
||||
|
||||
namespace nu {
|
||||
// hypothetical natural system of units for c=1
|
||||
|
||||
inline constexpr struct second_ : named_unit<"s"> {} second;
|
||||
inline constexpr struct minute_ : named_unit<"min", mag<60> * second> {} minute;
|
||||
inline constexpr struct second_ final : named_unit<"s"> {} second;
|
||||
inline constexpr struct minute_ final : named_unit<"min", mag<60> * second> {} minute;
|
||||
|
||||
inline constexpr struct time : system_reference<time_{}, second> {} time;
|
||||
inline constexpr struct length : system_reference<length_{}, second> {} length;
|
||||
@ -78,19 +78,19 @@ inline constexpr struct speed : system_reference<speed_{}, second / second> {} s
|
||||
}
|
||||
|
||||
// derived named units
|
||||
inline constexpr struct radian_ : named_unit<"rad", metre / metre, kind_of<angular_measure>> {} radian;
|
||||
inline constexpr struct steradian_ : named_unit<"sr", square(metre) / square(metre), kind_of<solid_angular_measure>> {} steradian;
|
||||
inline constexpr struct hertz_ : named_unit<"Hz", inverse(second), kind_of<frequency>> {} hertz;
|
||||
inline constexpr struct becquerel_ : named_unit<"Bq", inverse(second), kind_of<activity>> {} becquerel;
|
||||
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 radian_ final : named_unit<"rad", metre / metre, kind_of<angular_measure>> {} radian;
|
||||
inline constexpr struct steradian_ final : named_unit<"sr", square(metre) / square(metre), kind_of<solid_angular_measure>> {} steradian;
|
||||
inline constexpr struct hertz_ final : named_unit<"Hz", inverse(second), kind_of<frequency>> {} hertz;
|
||||
inline constexpr struct becquerel_ final : named_unit<"Bq", inverse(second), kind_of<activity>> {} becquerel;
|
||||
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 minute_ : named_unit<"min", mag<60> * second> {} minute;
|
||||
inline constexpr struct hour_ : named_unit<"h", mag<60> * minute> {} hour;
|
||||
inline constexpr struct kilometre_ : decltype(si::kilo<metre>) {} kilometre;
|
||||
inline constexpr struct minute_ final : named_unit<"min", mag<60> * second> {} minute;
|
||||
inline constexpr struct hour_ final : named_unit<"h", mag<60> * minute> {} hour;
|
||||
inline constexpr auto kilometre = si::kilo<metre>;
|
||||
|
||||
inline constexpr struct bit_ : named_unit<"bit", one, kind_of<storage_capacity>> {} bit;
|
||||
inline constexpr struct bit_ final : named_unit<"bit", one, kind_of<storage_capacity>> {} bit;
|
||||
// clang-format on
|
||||
|
||||
|
||||
@ -189,27 +189,27 @@ static_assert(
|
||||
constexpr auto m_per_s = speed[metre / second];
|
||||
static_assert(is_of_type<2 * m_per_s, quantity<reference<speed_, derived_unit<metre_, per<second_>>>{}, int>>);
|
||||
|
||||
static_assert(
|
||||
is_of_type<
|
||||
120 * length[kilometre] / (2 * time[hour]),
|
||||
quantity<reference<derived_quantity_spec<length_, per<time_>>, derived_unit<kilometre_, per<hour_>>>{}, int>>);
|
||||
static_assert(is_of_type<120 * length[kilometre] / (2 * time[hour]),
|
||||
quantity<reference<derived_quantity_spec<length_, per<time_>>,
|
||||
derived_unit<std::remove_const_t<decltype(si::kilo<metre>)>, per<hour_>>>{},
|
||||
int>>);
|
||||
static_assert(120 * length[kilometre] / (2 * time[hour]) == 60 * speed[kilometre / hour]);
|
||||
static_assert(
|
||||
is_of_type<
|
||||
[] {
|
||||
const auto distance = 120;
|
||||
const auto duration = 2;
|
||||
return distance * length[kilometre] / (duration * time[hour]);
|
||||
}(),
|
||||
quantity<reference<derived_quantity_spec<length_, per<time_>>, derived_unit<kilometre_, per<hour_>>>{}, int>>);
|
||||
static_assert(
|
||||
is_of_type<std::int64_t{120} * length[kilometre] / (2 * time[hour]),
|
||||
quantity<reference<derived_quantity_spec<length_, per<time_>>, derived_unit<kilometre_, per<hour_>>>{},
|
||||
std::int64_t>>);
|
||||
static_assert(
|
||||
is_of_type<120.L * length[kilometre] / (2 * time[hour]),
|
||||
quantity<reference<derived_quantity_spec<length_, per<time_>>, derived_unit<kilometre_, per<hour_>>>{},
|
||||
long double>>);
|
||||
static_assert(is_of_type<[] {
|
||||
const auto distance = 120;
|
||||
const auto duration = 2;
|
||||
return distance * length[kilometre] / (duration * time[hour]);
|
||||
}(),
|
||||
quantity<reference<derived_quantity_spec<length_, per<time_>>,
|
||||
derived_unit<std::remove_const_t<decltype(si::kilo<metre>)>, per<hour_>>>{},
|
||||
int>>);
|
||||
static_assert(is_of_type<std::int64_t{120} * length[kilometre] / (2 * time[hour]),
|
||||
quantity<reference<derived_quantity_spec<length_, per<time_>>,
|
||||
derived_unit<std::remove_const_t<decltype(si::kilo<metre>)>, per<hour_>>>{},
|
||||
std::int64_t>>);
|
||||
static_assert(is_of_type<120.L * length[kilometre] / (2 * time[hour]),
|
||||
quantity<reference<derived_quantity_spec<length_, per<time_>>,
|
||||
derived_unit<std::remove_const_t<decltype(si::kilo<metre>)>, per<hour_>>>{},
|
||||
long double>>);
|
||||
|
||||
static_assert(is_of_type<1. / 4 * area[square(metre)], decltype(1. * area[square(metre)] / 4)>);
|
||||
static_assert(1. / 4 * area[square(metre)] == 1. * area[square(metre)] / 4);
|
||||
@ -226,7 +226,9 @@ static_assert(is_of_type<42 * nu::length[nu::second] / (42 * nu::time[nu::second
|
||||
static_assert(is_of_type<42 * nu::speed[nu::second / nu::second], quantity<reference<speed_, one_>{}, int>>);
|
||||
static_assert(is_of_type<42 * nu::speed[one], quantity<reference<speed_, one_>{}, int>>);
|
||||
static_assert(is_of_type<42 * mass[kilogram] * (1 * nu::length[nu::second]) / (1 * nu::time[nu::second]),
|
||||
quantity<reference<derived_quantity_spec<length_, mass_, per<time_>>, kilogram_>{}, int>>);
|
||||
quantity<reference<derived_quantity_spec<length_, mass_, per<time_>>,
|
||||
std::remove_const_t<decltype(si::kilo<gram>)>>{},
|
||||
int>>);
|
||||
|
||||
template<auto dim, auto unit>
|
||||
concept invalid_nu_unit = !requires { dim[unit]; };
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user