refactor: 💥 from now on point origins must be marked final + absolute_point_origin does not use CRTP anymore

This commit is contained in:
Mateusz Pusz
2024-06-13 19:24:40 +02:00
parent bd6b1e654d
commit 05fc1e29c8
15 changed files with 93 additions and 97 deletions

View File

@ -10,7 +10,7 @@
- (!) feat: ABI concerns resolved with introduction of u8 strings for symbols - (!) feat: ABI concerns resolved with introduction of u8 strings for symbols
- (!) feat: API-related Conan, CMake, and preprocessor options redesigned - (!) feat: API-related Conan, CMake, and preprocessor options redesigned
- (!) feat: `core.h` removed - (!) feat: `core.h` removed
- (!) feat: from now on units, dimensions, and quantity specifications have to be marked as `final` - (!) feat: from now on units, dimensions, quantity specifications, and point origins have to be marked as `final`
- feat: implicit point origins support added - feat: implicit point origins support added
- feat: unit default point origin support added - feat: unit default point origin support added
- feat: `fma`, `isfinite`, `isinf`, and `isnan` math function added by [@NAThompson](https://github.com/NAThompson) - feat: `fma`, `isfinite`, `isinf`, and `isnan` math function added by [@NAThompson](https://github.com/NAThompson)
@ -47,6 +47,7 @@
- (!) refactor: `framework.h` introduced - (!) refactor: `framework.h` introduced
- (!) refactor: type list tools made an implementation detail of the library - (!) 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: 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: system's units do not inherit from one another anymore
- refactor: all units made `final` - refactor: all units made `final`
- refactor: math functions constraints refactored - refactor: math functions constraints refactored

View File

@ -205,7 +205,7 @@ origins. For example:
=== "Before" === "Before"
```cpp ```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; quantity_point price_usd = zero + 100 * USD;
``` ```
@ -300,16 +300,24 @@ is why it was renamed to `symbol_text` (:boom: **breaking change** :boom:).
``` ```
## Changes to dimension and quantity specification definitions ## Changes to dimension, quantity specification, and point origins definitions
Similarly to units, now also all dimensions and quantity specifications have to be marked final Similarly to units, now also all dimensions, quantity specifications, and point origins have to be
(:boom: **breaking change** :boom:). marked `final` (:boom: **breaking change** :boom:).
=== "Now" === "Now"
```cpp ```cpp
inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length; inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length;
inline constexpr struct length final : quantity_spec<dim_length> {} 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" === "Before"
@ -317,8 +325,18 @@ Similarly to units, now also all dimensions and quantity specifications have to
```cpp ```cpp
inline constexpr struct dim_length : base_dimension<"L"> {} dim_length; inline constexpr struct dim_length : base_dimension<"L"> {} dim_length;
inline constexpr struct length : quantity_spec<dim_length> {} 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 ## Improved text output

View File

@ -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) by the library's framework based on the [quantity equation](../../appendix/glossary.md#quantity-equation)
provided in the [quantity specification](../../appendix/glossary.md#quantity_spec). provided in the [quantity specification](../../appendix/glossary.md#quantity_spec).
All of the above dimensions have to be marked as `final`.
### `DimensionOf<T, V>` { #DimensionOf } ### `DimensionOf<T, V>` { #DimensionOf }
@ -42,6 +44,8 @@ including:
- Intermediate [derived quantity](../../appendix/glossary.md#derived-quantity) specifications being - Intermediate [derived quantity](../../appendix/glossary.md#derived-quantity) specifications being
a result of a [quantity equations](../../appendix/glossary.md#quantity-equation) on other specifications. a result of a [quantity equations](../../appendix/glossary.md#quantity-equation) on other specifications.
All of the above quantity specifications have to be marked as `final`.
### `QuantitySpecOf<T, V>` { #QuantitySpecOf } ### `QuantitySpecOf<T, V>` { #QuantitySpecOf }
@ -237,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: However, if we define `mean_sea_level` in the following way:
```cpp ```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 then it can't be used as a point origin for _points_ of `isq::length` or `isq::width` as none of them
@ -330,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>> { 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>; using T = std::chrono::time_point<C, std::chrono::seconds>;
static constexpr auto reference = si::second; 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; using rep = std::chrono::seconds::rep;
[[nodiscard]] static constexpr convert_implicitly<quantity<reference, rep>> to_quantity(const T& qp) [[nodiscard]] static constexpr convert_implicitly<quantity<reference, rep>> to_quantity(const T& qp)

View File

@ -346,13 +346,13 @@ For example:
- the absolute point origin can be defined in the following way: - the absolute point origin can be defined in the following way:
```cpp ```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: - the relative point origin can be defined in the following way:
```cpp ```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;
``` ```

View File

@ -172,7 +172,7 @@ origin.
![affine_space_2](affine_space_2.svg){style="width:80%;display: block;margin: 0 auto;"} ![affine_space_2](affine_space_2.svg){style="width:80%;display: block;margin: 0 auto;"}
```cpp ```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> qp1{100 * m}; // Compile-time error
// quantity_point<si::metre, origin> qp2{120 * 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 // 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 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 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 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:
![affine_space_3](affine_space_3.svg){style="width:80%;display: block;margin: 0 auto;"} ![affine_space_3](affine_space_3.svg){style="width:80%;display: block;margin: 0 auto;"}
```cpp ```cpp
inline constexpr struct origin1 : absolute_point_origin<origin1, isq::distance> {} origin1; inline constexpr struct origin1 final : absolute_point_origin<isq::distance> {} origin1;
inline constexpr struct origin2 : absolute_point_origin<origin2, isq::distance> {} origin2; inline constexpr struct origin2 final : absolute_point_origin<isq::distance> {} origin2;
quantity_point qp1 = origin1 + 100 * m; quantity_point qp1 = origin1 + 100 * m;
quantity_point qp2 = origin2 + 120 * m; quantity_point qp2 = origin2 + 120 * m;
@ -284,10 +276,10 @@ For such cases, relative point origins should be used:
![affine_space_4](affine_space_4.svg){style="width:80%;display: block;margin: 0 auto;"} ![affine_space_4](affine_space_4.svg){style="width:80%;display: block;margin: 0 auto;"}
```cpp ```cpp
inline constexpr struct A : absolute_point_origin<A, isq::distance> {} A; inline constexpr struct A final : absolute_point_origin<isq::distance> {} A;
inline constexpr struct B : relative_point_origin<A + 10 * m> {} B; inline constexpr struct B final : relative_point_origin<A + 10 * m> {} B;
inline constexpr struct C : relative_point_origin<B + 10 * m> {} C; inline constexpr struct C final : relative_point_origin<B + 10 * m> {} C;
inline constexpr struct D : relative_point_origin<A + 30 * m> {} D; inline constexpr struct D final : relative_point_origin<A + 30 * m> {} D;
quantity_point qp1 = C + 100 * m; quantity_point qp1 = C + 100 * m;
quantity_point qp2 = D + 120 * m; quantity_point qp2 = D + 120 * m;
@ -392,17 +384,17 @@ point origins for this purpose:
```cpp ```cpp
namespace si { namespace si {
inline constexpr struct absolute_zero : absolute_point_origin<absolute_zero, isq::thermodynamic_temperature> {} absolute_zero; inline constexpr struct absolute_zero final : absolute_point_origin<isq::thermodynamic_temperature> {} absolute_zero;
inline constexpr struct zeroth_kelvin : decltype(absolute_zero) {} zeroth_kelvin; 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 ice_point final : 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 auto zeroth_degree_Celsius = ice_point;
} }
namespace usc { 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; relative_point_origin<quantity_point{-32 * (mag_ratio<5, 9> * si::degree_Celsius)}> {} zeroth_degree_Fahrenheit;
} }
@ -481,7 +473,7 @@ the following way:
![affine_space_6](affine_space_6.svg){style="width:80%;display: block;margin: 0 auto;"} ![affine_space_6](affine_space_6.svg){style="width:80%;display: block;margin: 0 auto;"}
```cpp ```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>; using room_temp = quantity_point<isq::Celsius_temperature[deg_C], room_reference_temp>;
constexpr auto step_delta = isq::Celsius_temperature(0.5 * deg_C); constexpr auto step_delta = isq::Celsius_temperature(0.5 * deg_C);

View File

@ -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: to the `std::chrono` abstractions:
```cpp ```cpp
inline constexpr struct ts_origin : relative_point_origin<chrono_point_origin<system_clock> + 1 * h> {} ts_origin; inline constexpr struct ts_origin final : 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 my_origin final : absolute_point_origin<isq::time> {} my_origin;
quantity_point qp1 = sys_seconds{1s}; quantity_point qp1 = sys_seconds{1s};
auto tp1 = to_chrono_time_point(qp1); // OK auto tp1 = to_chrono_time_point(qp1); // OK

View File

@ -40,7 +40,7 @@ import mp_units;
namespace geographic { 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; } mean_sea_level;
using msl_altitude = mp_units::quantity_point<mp_units::isq::altitude[mp_units::si::metre], mean_sea_level>; using msl_altitude = mp_units::quantity_point<mp_units::isq::altitude[mp_units::si::metre], mean_sea_level>;
@ -68,10 +68,9 @@ struct MP_UNITS_STD_FMT::formatter<geographic::msl_altitude, Char> :
namespace geographic { 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; } equator;
inline constexpr struct prime_meridian : inline constexpr struct prime_meridian final : mp_units::absolute_point_origin<mp_units::isq::angular_measure> {
mp_units::absolute_point_origin<prime_meridian, mp_units::isq::angular_measure> {
} prime_meridian; } prime_meridian;

View File

@ -45,7 +45,7 @@ using namespace geographic;
enum class earth_gravity_model : std::int8_t { egm84_15, egm95_5, egm2008_1 }; enum class earth_gravity_model : std::int8_t { egm84_15, egm95_5, egm2008_1 };
template<earth_gravity_model M> 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; static constexpr earth_gravity_model egm = M;
}; };
template<earth_gravity_model M> template<earth_gravity_model M>
@ -115,7 +115,7 @@ hae_altitude<M> to_hae(msl_altitude msl, position<long double> pos)
// **** HAL **** // **** HAL ****
// clang-format off // 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 // clang-format on
using hal_altitude = quantity_point<isq::altitude[si::metre], height_above_launch>; using hal_altitude = quantity_point<isq::altitude[si::metre], height_above_launch>;

View File

@ -35,11 +35,10 @@
namespace mp_units { namespace mp_units {
MP_UNITS_EXPORT template<typename Derived, QuantitySpec auto QS> MP_UNITS_EXPORT template<QuantitySpec auto QS>
// NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility) // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)
struct absolute_point_origin { struct absolute_point_origin {
static constexpr QuantitySpec auto quantity_spec = QS; static constexpr QuantitySpec auto quantity_spec = QS;
using _type_ = absolute_point_origin;
}; };
MP_UNITS_EXPORT template<QuantityPoint auto QP> MP_UNITS_EXPORT template<QuantityPoint auto QP>
@ -56,7 +55,7 @@ struct relative_point_origin {
}; };
template<QuantitySpec auto QS> 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> MP_UNITS_EXPORT template<QuantitySpec auto QS>
inline constexpr zeroth_point_origin_<QS> zeroth_point_origin; 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) [[nodiscard]] consteval bool operator==(PO1 po1, PO2 po2)
{ {
if constexpr (detail::AbsolutePointOrigin<PO1> && detail::AbsolutePointOrigin<PO2>) if constexpr (detail::AbsolutePointOrigin<PO1> && detail::AbsolutePointOrigin<PO2>)
return is_same_v<typename PO1::_type_, typename PO2::_type_> || return is_same_v<PO1, PO2> || (detail::is_zeroth_point_origin(po1) && detail::is_zeroth_point_origin(po2) &&
(detail::is_zeroth_point_origin(po1) && detail::is_zeroth_point_origin(po2) && interconvertible(po1.quantity_spec, po2.quantity_spec));
interconvertible(po1.quantity_spec, po2.quantity_spec));
else if constexpr (detail::RelativePointOrigin<PO1> && detail::RelativePointOrigin<PO2>) else if constexpr (detail::RelativePointOrigin<PO1> && detail::RelativePointOrigin<PO2>)
return PO1::quantity_point == PO2::quantity_point; return PO1::quantity_point == PO2::quantity_point;
else if constexpr (detail::RelativePointOrigin<PO1>) else if constexpr (detail::RelativePointOrigin<PO1>)

View File

@ -32,7 +32,7 @@
namespace mp_units { namespace mp_units {
MP_UNITS_EXPORT template<typename Derived, QuantitySpec auto QS> MP_UNITS_EXPORT template<QuantitySpec auto QS>
struct absolute_point_origin; struct absolute_point_origin;
namespace detail { namespace detail {
@ -40,22 +40,15 @@ namespace detail {
template<typename T> template<typename T>
inline constexpr bool is_quantity_point = false; inline constexpr bool is_quantity_point = false;
template<typename T> template<auto Q>
inline constexpr bool is_specialization_of_absolute_point_origin = false; void to_base_specialization_of_absolute_point_origin(const volatile absolute_point_origin<Q>*);
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<typename T> template<typename T>
inline constexpr bool is_derived_from_specialization_of_absolute_point_origin = inline constexpr bool is_derived_from_specialization_of_absolute_point_origin =
requires(T* t) { to_base_specialization_of_absolute_point_origin(t); }; requires(T* t) { to_base_specialization_of_absolute_point_origin(t); };
template<typename T> template<typename T>
concept AbsolutePointOrigin = concept AbsolutePointOrigin = is_derived_from_specialization_of_absolute_point_origin<T> && std::is_final_v<T>;
is_derived_from_specialization_of_absolute_point_origin<T> && !is_specialization_of_absolute_point_origin<T>;
} // namespace detail } // namespace detail
@ -72,12 +65,6 @@ struct relative_point_origin;
namespace detail { 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> template<auto QP>
void to_base_specialization_of_relative_point_origin(const volatile relative_point_origin<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); }; requires(T* t) { to_base_specialization_of_relative_point_origin(t); };
template<typename T> template<typename T>
concept RelativePointOrigin = concept RelativePointOrigin = is_derived_from_specialization_of_relative_point_origin<T> && std::is_final_v<T>;
is_derived_from_specialization_of_relative_point_origin<T> && !is_specialization_of_relative_point_origin<T>;
} // namespace detail } // namespace detail

View File

@ -85,7 +85,7 @@ struct quantity_like_traits<std::chrono::duration<Rep, Period>> {
}; };
template<typename C> 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; using clock = C;
}; };
MP_UNITS_EXPORT template<typename C> MP_UNITS_EXPORT template<typename C>

View File

@ -44,8 +44,8 @@ inline constexpr struct gram final : named_unit<"g", kind_of<isq::mass>> {} gram
inline constexpr auto kilogram = kilo<gram>; inline constexpr auto kilogram = kilo<gram>;
inline constexpr struct ampere final : named_unit<"A", kind_of<isq::electric_current>> {} ampere; 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 absolute_zero final : absolute_point_origin<isq::thermodynamic_temperature> {} absolute_zero;
inline constexpr struct zeroth_kelvin : decltype(absolute_zero) {} zeroth_kelvin; 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 kelvin final : named_unit<"K", kind_of<isq::thermodynamic_temperature>, zeroth_kelvin> {} kelvin;
inline constexpr struct mole final : named_unit<"mol", kind_of<isq::amount_of_substance>> {} mole; inline constexpr struct mole final : named_unit<"mol", kind_of<isq::amount_of_substance>> {} mole;
@ -77,8 +77,8 @@ 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 tesla final : named_unit<"T", weber / square(metre)> {} tesla;
inline constexpr struct henry final : named_unit<"H", weber / ampere> {} henry; 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 ice_point final : 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 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 degree_Celsius final : named_unit<symbol_text{u8"°C", "`C"}, kelvin, zeroth_degree_Celsius> {} degree_Celsius;
inline constexpr struct lumen final : named_unit<"lm", candela * steradian> {} lumen; inline constexpr struct lumen final : named_unit<"lm", candela * steradian> {} lumen;

View File

@ -118,7 +118,7 @@ inline constexpr struct troy_pound final : named_unit<"lb t", mag<12> * troy_onc
inline constexpr struct inch_of_mercury final : 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 // 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 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; 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 // clang-format on

View File

@ -40,9 +40,9 @@ namespace {
using namespace mp_units; 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; } 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; } my_relative_origin;
inline constexpr auto dim_speed = isq::dim_length / isq::dim_time; inline constexpr auto dim_speed = isq::dim_length / isq::dim_time;
@ -360,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_origin>>);
static_assert(QuantityPoint<quantity_point<isq::radius[si::metre], my_relative_origin>>); static_assert(QuantityPoint<quantity_point<isq::radius[si::metre], my_relative_origin>>);
static_assert(!QuantityPoint<decltype(isq::length[si::metre])>); 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_origin>);
static_assert(!QuantityPoint<struct my_relative_origin>); static_assert(!QuantityPoint<struct my_relative_origin>);
#if MP_UNITS_HOSTED #if MP_UNITS_HOSTED
@ -394,7 +394,7 @@ static_assert(QuantityPointOf<quantity_point<isq::radius[si::metre], my_relative
// PointOrigin // PointOrigin
static_assert(PointOrigin<struct my_origin>); static_assert(PointOrigin<struct my_origin>);
static_assert(PointOrigin<struct my_relative_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<relative_point_origin<my_origin + 42 * si::metre>>);
static_assert(!PointOrigin<quantity_point<si::metre, my_origin>>); static_assert(!PointOrigin<quantity_point<si::metre, my_origin>>);
static_assert(!PointOrigin<quantity_point<isq::length[si::metre], my_origin>>); static_assert(!PointOrigin<quantity_point<isq::length[si::metre], my_origin>>);

View File

@ -46,40 +46,38 @@ using namespace std::chrono_literals;
using sys_seconds = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>; using sys_seconds = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
#endif #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; } 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; } mean_sea_level;
inline constexpr struct my_mean_sea_level : decltype(mean_sea_level) { inline constexpr auto my_mean_sea_level = mean_sea_level;
} my_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; } 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; } ground_level;
inline constexpr struct my_ground_level : decltype(ground_level) { inline constexpr auto my_ground_level = ground_level;
} my_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; } 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; } 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; } 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; } 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; } other_absolute_level;
inline constexpr struct zero : absolute_point_origin<zero, dimensionless> { inline constexpr struct zero final : absolute_point_origin<dimensionless> {
} zero; } zero;
QUANTITY_SPEC(special_height, isq::height); 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); static_assert(ground_level != other_ground_level);
template<auto QS> template<auto QS>
struct absolute_po_ : absolute_point_origin<absolute_po_<QS>, QS> {}; struct absolute_po_ final : absolute_point_origin<QS> {};
template<auto QS> template<auto QS>
inline constexpr absolute_po_<QS> absolute_po; inline constexpr absolute_po_<QS> absolute_po;
template<auto QP> template<auto QP>
struct relative_po_ : relative_point_origin<QP> {}; struct relative_po_ final : relative_point_origin<QP> {};
template<auto QP> template<auto QP>
inline constexpr relative_po_<QP> relative_po; inline constexpr relative_po_<QP> relative_po;
@ -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(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>::point_origin, struct si::ice_point>);
static_assert( 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 == static_assert(quantity_point<isq::Celsius_temperature[si::degree_Celsius], si::ice_point>::reference ==
isq::Celsius_temperature[si::degree_Celsius]); 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>); struct si::ice_point>);
static_assert( static_assert(
is_of_type<quantity_point<isq::Celsius_temperature[si::degree_Celsius], si::ice_point>::absolute_point_origin, 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(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<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)>, static_assert(
struct si::zeroth_degree_Celsius>); 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)>, 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}.unit == si::degree_Celsius);
static_assert(quantity_point{20 * deg_C}.quantity_spec == kind_of<isq::thermodynamic_temperature>); 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(other_ground_level - tower_peak == 39 * m);
static_assert(tower_peak - other_ground_level == -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; } zero_m_per_s;
// commutativity and associativity // 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])), 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>>); 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; } zero_Hz;
static_assert(((zero_Hz + 10 / (2 * isq::period_duration[s])) + 5 * isq::frequency[Hz]).quantity_from(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); }; 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; } zero_Bq;
static_assert(invalid_addition(zero_Bq + 5 * isq::activity[Bq], 5 * isq::frequency[Hz])); static_assert(invalid_addition(zero_Bq + 5 * isq::activity[Bq], 5 * isq::frequency[Hz]));