mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 18:37:15 +02:00
feat: 💥 from now on quantity specifications have to be marked as final
This commit is contained in:
@ -97,15 +97,15 @@ enumeration can be appended to the `quantity_spec` describing such a quantity ty
|
|||||||
=== "C++23"
|
=== "C++23"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct position_vector : quantity_spec<length, quantity_character::vector> {} position_vector;
|
inline constexpr struct position_vector final : quantity_spec<length, quantity_character::vector> {} position_vector;
|
||||||
inline constexpr struct displacement : quantity_spec<length, quantity_character::vector> {} displacement;
|
inline constexpr struct displacement final : quantity_spec<length, quantity_character::vector> {} displacement;
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "C++20"
|
=== "C++20"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct position_vector : quantity_spec<position_vector, length, quantity_character::vector> {} position_vector;
|
inline constexpr struct position_vector final : 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 displacement final : quantity_spec<displacement, length, quantity_character::vector> {} displacement;
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Portable"
|
=== "Portable"
|
||||||
@ -126,13 +126,13 @@ character override is needed):
|
|||||||
=== "C++23"
|
=== "C++23"
|
||||||
|
|
||||||
```cpp
|
```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"
|
=== "C++20"
|
||||||
|
|
||||||
```cpp
|
```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"
|
=== "Portable"
|
||||||
|
@ -71,9 +71,9 @@ provided in the [quantity specification](../../appendix/glossary.md#quantity_spe
|
|||||||
=== "C++23"
|
=== "C++23"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct length : quantity_spec<dim_length> {} length;
|
inline constexpr struct length final : quantity_spec<dim_length> {} length;
|
||||||
inline constexpr struct time : quantity_spec<dim_time> {} time;
|
inline constexpr struct time final : quantity_spec<dim_time> {} time;
|
||||||
inline constexpr struct speed : quantity_spec<length / time> {} speed;
|
inline constexpr struct speed final : quantity_spec<length / time> {} speed;
|
||||||
|
|
||||||
static_assert(speed.dimension == dim_length / dim_time);
|
static_assert(speed.dimension == dim_length / dim_time);
|
||||||
```
|
```
|
||||||
@ -81,9 +81,9 @@ provided in the [quantity specification](../../appendix/glossary.md#quantity_spe
|
|||||||
=== "C++20"
|
=== "C++20"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct length : quantity_spec<length, dim_length> {} length;
|
inline constexpr struct length final : quantity_spec<length, dim_length> {} length;
|
||||||
inline constexpr struct time : quantity_spec<time, dim_time> {} time;
|
inline constexpr struct time final : quantity_spec<time, dim_time> {} time;
|
||||||
inline constexpr struct speed : quantity_spec<speed, length / time> {} speed;
|
inline constexpr struct speed final : quantity_spec<speed, length / time> {} speed;
|
||||||
|
|
||||||
static_assert(speed.dimension == dim_length / dim_time);
|
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"
|
=== "C++23"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct length : quantity_spec<dim_length> {} length;
|
inline constexpr struct length final : quantity_spec<dim_length> {} length;
|
||||||
inline constexpr struct height : quantity_spec<length> {} height;
|
inline constexpr struct height final : quantity_spec<length> {} height;
|
||||||
inline constexpr struct speed : quantity_spec<length / time> {} speed;
|
inline constexpr struct speed final : quantity_spec<length / time> {} speed;
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "C++20"
|
=== "C++20"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct length : quantity_spec<length, dim_length> {} length;
|
inline constexpr struct length final : quantity_spec<length, dim_length> {} length;
|
||||||
inline constexpr struct height : quantity_spec<height, length> {} height;
|
inline constexpr struct height final : quantity_spec<height, length> {} height;
|
||||||
inline constexpr struct speed : quantity_spec<speed, length / time> {} speed;
|
inline constexpr struct speed final : quantity_spec<speed, length / time> {} speed;
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Portable"
|
=== "Portable"
|
||||||
|
@ -217,17 +217,17 @@ to the quantity specification:
|
|||||||
=== "C++23"
|
=== "C++23"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct angular_measure : quantity_spec<dimensionless, arc_length / radius, is_kind> {} angular_measure;
|
inline constexpr struct angular_measure final : 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 solid_angular_measure final : 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 storage_capacity final : quantity_spec<dimensionless, is_kind> {} storage_capacity;
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "C++20"
|
=== "C++20"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct angular_measure : quantity_spec<angular_measure, dimensionless, arc_length / radius, is_kind> {} angular_measure;
|
inline constexpr struct angular_measure final : 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 solid_angular_measure final : 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 storage_capacity final : quantity_spec<storage_capacity, dimensionless, is_kind> {} storage_capacity;
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Portable"
|
=== "Portable"
|
||||||
|
@ -316,13 +316,13 @@ Let's see another example:
|
|||||||
using namespace mp_units;
|
using namespace mp_units;
|
||||||
|
|
||||||
// add a custom quantity type of kind isq::length
|
// add a custom quantity type of kind isq::length
|
||||||
inline constexpr struct horizontal_length
|
inline constexpr struct horizontal_length final :
|
||||||
: quantity_spec<isq::length> {} horizontal_length;
|
quantity_spec<isq::length> {} horizontal_length;
|
||||||
|
|
||||||
// add a custom derived quantity type of kind isq::area
|
// add a custom derived quantity type of kind isq::area
|
||||||
// with a constrained quantity equation
|
// with a constrained quantity equation
|
||||||
inline constexpr struct horizontal_area
|
inline constexpr struct horizontal_area final :
|
||||||
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||||
|
|
||||||
class StorageTank {
|
class StorageTank {
|
||||||
quantity<horizontal_area[square(si::metre)]> base_;
|
quantity<horizontal_area[square(si::metre)]> base_;
|
||||||
@ -429,13 +429,13 @@ Let's see another example:
|
|||||||
using namespace mp_units;
|
using namespace mp_units;
|
||||||
|
|
||||||
// add a custom quantity type of kind isq::length
|
// add a custom quantity type of kind isq::length
|
||||||
inline constexpr struct horizontal_length
|
inline constexpr struct horizontal_length final :
|
||||||
: quantity_spec<isq::length> {} horizontal_length;
|
quantity_spec<isq::length> {} horizontal_length;
|
||||||
|
|
||||||
// add a custom derived quantity type of kind isq::area
|
// add a custom derived quantity type of kind isq::area
|
||||||
// with a constrained quantity equation
|
// with a constrained quantity equation
|
||||||
inline constexpr struct horizontal_area
|
inline constexpr struct horizontal_area final :
|
||||||
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||||
|
|
||||||
class StorageTank {
|
class StorageTank {
|
||||||
quantity<horizontal_area[square(si::metre)]> base_;
|
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"
|
=== "C++23"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct length : quantity_spec<dim_length> {} length;
|
inline constexpr struct length final : quantity_spec<dim_length> {} length;
|
||||||
inline constexpr struct width : quantity_spec<length> {} width;
|
inline constexpr struct width final : quantity_spec<length> {} width;
|
||||||
inline constexpr auto breadth = 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 depth = height;
|
||||||
inline constexpr auto altitude = height;
|
inline constexpr auto altitude = height;
|
||||||
inline constexpr struct thickness : quantity_spec<width> {} thickness;
|
inline constexpr struct thickness final : quantity_spec<width> {} thickness;
|
||||||
inline constexpr struct diameter : quantity_spec<width> {} diameter;
|
inline constexpr struct diameter final : quantity_spec<width> {} diameter;
|
||||||
inline constexpr struct radius : quantity_spec<width> {} radius;
|
inline constexpr struct radius final : quantity_spec<width> {} radius;
|
||||||
inline constexpr struct radius_of_curvature : quantity_spec<radius> {} radius_of_curvature;
|
inline constexpr struct radius_of_curvature final : quantity_spec<radius> {} radius_of_curvature;
|
||||||
inline constexpr struct path_length : quantity_spec<length> {} path_length;
|
inline constexpr struct path_length final : quantity_spec<length> {} path_length;
|
||||||
inline constexpr auto arc_length = path_length;
|
inline constexpr auto arc_length = path_length;
|
||||||
inline constexpr struct distance : quantity_spec<path_length> {} distance;
|
inline constexpr struct distance final : quantity_spec<path_length> {} distance;
|
||||||
inline constexpr struct radial_distance : quantity_spec<distance> {} radial_distance;
|
inline constexpr struct radial_distance final : quantity_spec<distance> {} radial_distance;
|
||||||
inline constexpr struct wavelength : quantity_spec<length> {} wavelength;
|
inline constexpr struct wavelength final : quantity_spec<length> {} wavelength;
|
||||||
inline constexpr struct position_vector : quantity_spec<length, quantity_character::vector> {} position_vector;
|
inline constexpr struct position_vector final : quantity_spec<length, quantity_character::vector> {} position_vector;
|
||||||
inline constexpr struct displacement : quantity_spec<length, quantity_character::vector> {} displacement;
|
inline constexpr struct displacement final : quantity_spec<length, quantity_character::vector> {} displacement;
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "C++20"
|
=== "C++20"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct length : quantity_spec<length, dim_length> {} length;
|
inline constexpr struct length final : quantity_spec<length, dim_length> {} length;
|
||||||
inline constexpr struct width : quantity_spec<width, length> {} width;
|
inline constexpr struct width final : quantity_spec<width, length> {} width;
|
||||||
inline constexpr auto breadth = 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 depth = height;
|
||||||
inline constexpr auto altitude = height;
|
inline constexpr auto altitude = height;
|
||||||
inline constexpr struct thickness : quantity_spec<thickness, width> {} thickness;
|
inline constexpr struct thickness final : quantity_spec<thickness, width> {} thickness;
|
||||||
inline constexpr struct diameter : quantity_spec<diameter, width> {} diameter;
|
inline constexpr struct diameter final : quantity_spec<diameter, width> {} diameter;
|
||||||
inline constexpr struct radius : quantity_spec<radius, width> {} radius;
|
inline constexpr struct radius final : quantity_spec<radius, width> {} radius;
|
||||||
inline constexpr struct radius_of_curvature : quantity_spec<radius_of_curvature, radius> {} radius_of_curvature;
|
inline constexpr struct radius_of_curvature final : quantity_spec<radius_of_curvature, radius> {} radius_of_curvature;
|
||||||
inline constexpr struct path_length : quantity_spec<path_length, length> {} path_length;
|
inline constexpr struct path_length final : quantity_spec<path_length, length> {} path_length;
|
||||||
inline constexpr auto arc_length = path_length;
|
inline constexpr auto arc_length = path_length;
|
||||||
inline constexpr struct distance : quantity_spec<distance, path_length> {} distance;
|
inline constexpr struct distance final : quantity_spec<distance, path_length> {} distance;
|
||||||
inline constexpr struct radial_distance : quantity_spec<radial_distance, distance> {} radial_distance;
|
inline constexpr struct radial_distance final : quantity_spec<radial_distance, distance> {} radial_distance;
|
||||||
inline constexpr struct wavelength : quantity_spec<wavelength, length> {} wavelength;
|
inline constexpr struct wavelength final : quantity_spec<wavelength, length> {} wavelength;
|
||||||
inline constexpr struct position_vector : quantity_spec<position_vector, length, quantity_character::vector> {} position_vector;
|
inline constexpr struct position_vector final : 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 displacement final : quantity_spec<displacement, length, quantity_character::vector> {} displacement;
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Portable"
|
=== "Portable"
|
||||||
|
@ -86,7 +86,7 @@ the `value_cast<U, Rep>(q)` which always returns the most precise result:
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency;
|
inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency;
|
||||||
inline constexpr struct currency : quantity_spec<dim_currency> {} currency;
|
inline constexpr struct currency final : quantity_spec<dim_currency> {} currency;
|
||||||
|
|
||||||
inline constexpr struct us_dollar final : named_unit<"USD", kind_of<currency>> {} 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;
|
inline constexpr struct scaled_us_dollar final : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
|
||||||
@ -106,7 +106,7 @@ the `value_cast<U, Rep>(q)` which always returns the most precise result:
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency;
|
inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency;
|
||||||
inline constexpr struct currency : quantity_spec<currency, dim_currency> {} currency;
|
inline constexpr struct currency final : quantity_spec<currency, dim_currency> {} currency;
|
||||||
|
|
||||||
inline constexpr struct us_dollar final : named_unit<"USD", kind_of<currency>> {} 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;
|
inline constexpr struct scaled_us_dollar final : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
|
@ -35,10 +35,10 @@ add_mp_units_module(
|
|||||||
core mp-units-core
|
core mp-units-core
|
||||||
HEADERS include/mp-units/bits/core_gmf.h
|
HEADERS include/mp-units/bits/core_gmf.h
|
||||||
include/mp-units/bits/get_associated_quantity.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/hacks.h
|
||||||
include/mp-units/bits/math_concepts.h
|
include/mp-units/bits/math_concepts.h
|
||||||
include/mp-units/bits/module_macros.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/ratio.h
|
||||||
include/mp-units/bits/sudo_cast.h
|
include/mp-units/bits/sudo_cast.h
|
||||||
include/mp-units/bits/text_tools.h
|
include/mp-units/bits/text_tools.h
|
||||||
|
@ -88,4 +88,19 @@ template<QuantitySpec A, QuantitySpec B>
|
|||||||
return get_common_base_for_hierarchy_of_equal_length(a, hierarchy_path_advance<b_length - a_length>(b));
|
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 auto is_child_of(Child ch, Parent)
|
||||||
|
{
|
||||||
|
if constexpr (Child{} == Parent{})
|
||||||
|
return std::true_type{};
|
||||||
|
else {
|
||||||
|
constexpr auto child_length = hierarchy_path_length(Child{});
|
||||||
|
constexpr auto parent_length = hierarchy_path_length(Parent{});
|
||||||
|
if constexpr (parent_length > child_length)
|
||||||
|
return std::false_type{};
|
||||||
|
else
|
||||||
|
return std::bool_constant<hierarchy_path_advance<child_length - parent_length>(ch) == Parent{}>{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mp_units::detail
|
} // namespace mp_units::detail
|
@ -28,14 +28,14 @@
|
|||||||
|
|
||||||
#ifdef MP_UNITS_API_NO_CRTP
|
#ifdef MP_UNITS_API_NO_CRTP
|
||||||
|
|
||||||
#define QUANTITY_SPEC(name, ...) \
|
#define QUANTITY_SPEC(name, ...) \
|
||||||
inline constexpr struct name : ::mp_units::quantity_spec<__VA_ARGS__> { \
|
inline constexpr struct name final : ::mp_units::quantity_spec<__VA_ARGS__> { \
|
||||||
} name
|
} name
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define QUANTITY_SPEC(name, ...) \
|
#define QUANTITY_SPEC(name, ...) \
|
||||||
inline constexpr struct name : ::mp_units::quantity_spec<name, __VA_ARGS__> { \
|
inline constexpr struct name final : ::mp_units::quantity_spec<name, __VA_ARGS__> { \
|
||||||
} name
|
} name
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// IWYU pragma: private, include <mp-units/framework.h>
|
// 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/hacks.h>
|
||||||
#include <mp-units/bits/module_macros.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/compat_macros.h>
|
||||||
#include <mp-units/ext/algorithm.h>
|
#include <mp-units/ext/algorithm.h>
|
||||||
#include <mp-units/ext/type_name.h>
|
#include <mp-units/ext/type_name.h>
|
||||||
@ -203,9 +203,9 @@ MP_UNITS_EXPORT_END
|
|||||||
* inline constexpr struct dim_mass final : base_dimension<"M"> {} dim_mass;
|
* 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_time final : base_dimension<"T"> {} dim_time;
|
||||||
*
|
*
|
||||||
* inline constexpr struct length : quantity_spec<dim_length> {} length;
|
* inline constexpr struct length final : quantity_spec<dim_length> {} length;
|
||||||
* inline constexpr struct mass : quantity_spec<dim_mass> {} mass;
|
* inline constexpr struct mass final : quantity_spec<dim_mass> {} mass;
|
||||||
* inline constexpr struct time : quantity_spec<dim_time> {} time;
|
* inline constexpr struct time final : quantity_spec<dim_time> {} time;
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
* @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)>)
|
requires(... && !QuantitySpec<decltype(Args)>)
|
||||||
struct quantity_spec<Self, Dim, Args...> : detail::quantity_spec_interface<Self> {
|
struct quantity_spec<Self, Dim, Args...> : detail::quantity_spec_interface<Self> {
|
||||||
#endif
|
#endif
|
||||||
|
using _base_type_ = quantity_spec;
|
||||||
static constexpr detail::BaseDimension auto dimension = Dim;
|
static constexpr detail::BaseDimension auto dimension = Dim;
|
||||||
static constexpr quantity_character character = detail::quantity_character_init<Args...>(quantity_character::scalar);
|
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:
|
* For example:
|
||||||
*
|
*
|
||||||
* @code{.cpp}
|
* @code{.cpp}
|
||||||
* inline constexpr struct area : quantity_spec<pow<2>(length)> {} area;
|
* inline constexpr struct area final : quantity_spec<pow<2>(length)> {} area;
|
||||||
* inline constexpr struct volume : quantity_spec<pow<3>(length)> {} volume;
|
* inline constexpr struct volume final : quantity_spec<pow<3>(length)> {} volume;
|
||||||
* inline constexpr struct velocity : quantity_spec<position_vector / duration> {} velocity;
|
* inline constexpr struct velocity final : quantity_spec<position_vector / duration> {} velocity;
|
||||||
* inline constexpr struct speed : quantity_spec<length / time> {} speed;
|
* inline constexpr struct speed final : quantity_spec<length / time> {} speed;
|
||||||
* inline constexpr struct force : quantity_spec<mass * acceleration, quantity_character::vector> {} force;
|
* inline constexpr struct force final : quantity_spec<mass * acceleration, quantity_character::vector> {} force;
|
||||||
* inline constexpr struct power : quantity_spec<force * velocity, quantity_character::scalar> {} power;
|
* inline constexpr struct power final : quantity_spec<force * velocity, quantity_character::scalar> {} power;
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
||||||
@ -268,11 +269,24 @@ template<typename Self, detail::DerivedQuantitySpec auto Eq, one_of<quantity_cha
|
|||||||
requires(... && !QuantitySpec<decltype(Args)>)
|
requires(... && !QuantitySpec<decltype(Args)>)
|
||||||
struct quantity_spec<Self, Eq, Args...> : detail::quantity_spec_interface<Self> {
|
struct quantity_spec<Self, Eq, Args...> : detail::quantity_spec_interface<Self> {
|
||||||
#endif
|
#endif
|
||||||
|
using _base_type_ = quantity_spec;
|
||||||
static constexpr auto _equation_ = Eq;
|
static constexpr auto _equation_ = Eq;
|
||||||
static constexpr Dimension auto dimension = Eq.dimension;
|
static constexpr Dimension auto dimension = Eq.dimension;
|
||||||
static constexpr quantity_character character = detail::quantity_character_init<Args...>(Eq.character);
|
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
|
* @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:
|
* For example:
|
||||||
*
|
*
|
||||||
* @code{.cpp}
|
* @code{.cpp}
|
||||||
* inline constexpr struct width : quantity_spec<length> {} width;
|
* inline constexpr struct width final : quantity_spec<length> {} width;
|
||||||
* inline constexpr struct height : quantity_spec<length> {} height;
|
* inline constexpr struct height final : quantity_spec<length> {} height;
|
||||||
* inline constexpr struct diameter : quantity_spec<width> {} diameter;
|
* inline constexpr struct diameter final : quantity_spec<width> {} diameter;
|
||||||
* inline constexpr struct position_vector : quantity_spec<length, quantity_character::vector> {} position_vector;
|
* inline constexpr struct position_vector final : quantity_spec<length, quantity_character::vector> {} position_vector;
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
* @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
|
#ifdef MP_UNITS_API_NO_CRTP
|
||||||
template<detail::NamedQuantitySpec auto QS, one_of<quantity_character, struct is_kind> auto... Args>
|
template<detail::NamedQuantitySpec auto QS, one_of<quantity_character, struct is_kind> auto... Args>
|
||||||
requires(... && !QuantitySpec<decltype(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
|
#else
|
||||||
template<typename Self, detail::NamedQuantitySpec auto QS, one_of<quantity_character, struct is_kind> auto... Args>
|
template<typename Self, detail::NamedQuantitySpec auto QS, one_of<quantity_character, struct is_kind> auto... Args>
|
||||||
requires(... && !QuantitySpec<decltype(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
|
#endif
|
||||||
|
using _base_type_ = quantity_spec;
|
||||||
static constexpr auto _parent_ = QS;
|
static constexpr auto _parent_ = QS;
|
||||||
|
static constexpr Dimension auto dimension = _parent_.dimension;
|
||||||
static constexpr quantity_character character = detail::quantity_character_init<Args...>(QS.character);
|
static constexpr quantity_character character = detail::quantity_character_init<Args...>(QS.character);
|
||||||
|
|
||||||
#ifndef MP_UNITS_API_NO_CRTP
|
#ifndef MP_UNITS_API_NO_CRTP
|
||||||
@ -330,6 +346,7 @@ struct quantity_spec<Self, QS, Args...> : decltype(QS) {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
/**
|
/**
|
||||||
* @brief Specialization defining a leaf derived quantity in the hierarchy and refining paren't equation
|
* @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:
|
* For example:
|
||||||
*
|
*
|
||||||
* @code{.cpp}
|
* @code{.cpp}
|
||||||
* inline constexpr struct angular_measure : quantity_spec<dimensionless, arc_length / radius, is_kind> {}
|
* inline constexpr struct angular_measure final : quantity_spec<dimensionless, arc_length / radius, is_kind> {} angular_measure;
|
||||||
* angular_measure; inline constexpr struct velocity : quantity_spec<speed, position_vector / duration> {} velocity;
|
* inline constexpr struct velocity final : quantity_spec<speed, position_vector / duration> {} velocity;
|
||||||
* inline constexpr struct weight : quantity_spec<force, mass * acceleration_of_free_fall> {} weight;
|
* inline constexpr struct weight final : 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 kinetic_energy final : quantity_spec<mechanical_energy, mass * pow<2>(speed)> {} kinetic_energy;
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @note A common convention in this library is to assign the same name for a type and an object of this type.
|
* @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
|
* @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
|
* or `is_kind` in case the quantity starts a new hierarchy tree of a kind
|
||||||
*/
|
*/
|
||||||
|
// clang-format on
|
||||||
#ifdef MP_UNITS_API_NO_CRTP
|
#ifdef MP_UNITS_API_NO_CRTP
|
||||||
template<detail::NamedQuantitySpec auto QS, detail::DerivedQuantitySpec auto Eq,
|
template<detail::NamedQuantitySpec auto QS, detail::DerivedQuantitySpec auto Eq,
|
||||||
one_of<quantity_character, struct is_kind> auto... Args>
|
one_of<quantity_character, struct is_kind> auto... Args>
|
||||||
requires(!requires { QS._equation_; } || (requires {
|
requires(!requires { QS._equation_; } || (requires {
|
||||||
QS._equation_;
|
QS._equation_;
|
||||||
} && (explicitly_convertible(Eq, QS._equation_)))) && (... && !QuantitySpec<decltype(Args)>)
|
} && (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
|
#else
|
||||||
template<typename Self, detail::NamedQuantitySpec auto QS, detail::DerivedQuantitySpec auto Eq,
|
template<typename Self, detail::NamedQuantitySpec auto QS, detail::DerivedQuantitySpec auto Eq,
|
||||||
one_of<quantity_character, struct is_kind> auto... Args>
|
one_of<quantity_character, struct is_kind> auto... Args>
|
||||||
requires(!requires { QS._equation_; } || (requires {
|
requires(!requires { QS._equation_; } || (requires {
|
||||||
QS._equation_;
|
QS._equation_;
|
||||||
} && (explicitly_convertible(Eq, QS._equation_)))) && (... && !QuantitySpec<decltype(Args)>)
|
} && (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
|
#endif
|
||||||
|
using _base_type_ = quantity_spec;
|
||||||
|
static constexpr auto _parent_ = QS;
|
||||||
static constexpr auto _equation_ = Eq;
|
static constexpr auto _equation_ = Eq;
|
||||||
|
static constexpr Dimension auto dimension = _parent_.dimension;
|
||||||
static constexpr quantity_character character = detail::quantity_character_init<Args...>(Eq.character);
|
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
|
* @brief A specification of a derived quantity
|
||||||
@ -422,21 +464,7 @@ struct quantity_spec<Self, QS, Eq, Args...> : quantity_spec<Self, QS, Args...> {
|
|||||||
* instantiate this type automatically based on the dimensional arithmetic equation provided by the user.
|
* instantiate this type automatically based on the dimensional arithmetic equation provided by the user.
|
||||||
*/
|
*/
|
||||||
template<detail::DerivedQuantitySpecExpr... Expr>
|
template<detail::DerivedQuantitySpecExpr... Expr>
|
||||||
struct derived_quantity_spec :
|
struct derived_quantity_spec final : detail::derived_quantity_spec_impl<Expr...> {};
|
||||||
#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_{});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Quantity of dimension one
|
* @brief Quantity of dimension one
|
||||||
@ -446,6 +474,13 @@ struct derived_quantity_spec :
|
|||||||
*/
|
*/
|
||||||
MP_UNITS_EXPORT QUANTITY_SPEC(dimensionless, 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
|
* @brief Quantity kind specifier
|
||||||
*
|
*
|
||||||
@ -464,7 +499,8 @@ template<QuantitySpec Q>
|
|||||||
#ifdef MP_UNITS_API_NO_CRTP
|
#ifdef MP_UNITS_API_NO_CRTP
|
||||||
template<typename Q>
|
template<typename Q>
|
||||||
requires detail::QuantitySpecWithNoSpecifiers<Q> && (detail::get_kind_tree_root(Q{}) == 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{};
|
static constexpr auto _quantity_spec_ = Q{};
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
@ -476,7 +512,8 @@ template<typename Q>
|
|||||||
template<detail::QuantitySpecWithNoSpecifiers Q>
|
template<detail::QuantitySpecWithNoSpecifiers Q>
|
||||||
requires(detail::get_kind_tree_root(Q{}) == Q{})
|
requires(detail::get_kind_tree_root(Q{}) == Q{})
|
||||||
#endif
|
#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{};
|
static constexpr auto _quantity_spec_ = Q{};
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -487,9 +524,6 @@ inline constexpr kind_of_<MP_UNITS_REMOVE_CONST(decltype(Q))> kind_of;
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<>
|
|
||||||
struct is_dimensionless<struct dimensionless> : std::true_type {};
|
|
||||||
|
|
||||||
template<QuantitySpec auto... From, QuantitySpec Q>
|
template<QuantitySpec auto... From, QuantitySpec Q>
|
||||||
[[nodiscard]] consteval QuantitySpec auto clone_kind_of(Q q)
|
[[nodiscard]] consteval QuantitySpec auto clone_kind_of(Q q)
|
||||||
{
|
{
|
||||||
@ -1353,8 +1387,8 @@ template<NamedQuantitySpec From, NamedQuantitySpec To>
|
|||||||
using enum specs_convertible_result;
|
using enum specs_convertible_result;
|
||||||
|
|
||||||
if constexpr (have_common_base(From{}, To{})) {
|
if constexpr (have_common_base(From{}, To{})) {
|
||||||
if constexpr (std::derived_from<From, To>) return yes;
|
if constexpr (decltype(is_child_of(From{}, To{}))::value) return yes;
|
||||||
if constexpr (std::derived_from<To, From>) return explicit_conversion;
|
if constexpr (decltype(is_child_of(To{}, From{}))::value) return explicit_conversion;
|
||||||
if constexpr (get_kind(From{}) == get_kind(To{})) return cast;
|
if constexpr (get_kind(From{}) == get_kind(To{})) return cast;
|
||||||
return no;
|
return no;
|
||||||
} else if constexpr (get_kind(From{}) != get_kind(To{}))
|
} else if constexpr (get_kind(From{}) != get_kind(To{}))
|
||||||
|
@ -64,25 +64,14 @@ template<typename T>
|
|||||||
inline constexpr bool is_derived_from_specialization_of_quantity_spec =
|
inline constexpr bool is_derived_from_specialization_of_quantity_spec =
|
||||||
requires(T* t) { to_base_specialization_of_quantity_spec(t); };
|
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
|
* @brief Concept matching all named quantity specification types
|
||||||
*
|
*
|
||||||
* Satisfied by all types that derive from `quantity_spec`.
|
* Satisfied by all types that derive from `quantity_spec`.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept NamedQuantitySpec = is_derived_from_specialization_of_quantity_spec<T> &&
|
concept NamedQuantitySpec =
|
||||||
(!is_specialization_of_quantity_spec<T>)&&(!QuantityKindSpec<T>);
|
is_derived_from_specialization_of_quantity_spec<T> && std::is_final_v<T> && (!QuantityKindSpec<T>);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_dimensionless : std::false_type {};
|
struct is_dimensionless : std::false_type {};
|
||||||
@ -136,12 +125,15 @@ MP_UNITS_EXPORT template<QuantitySpec Q>
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
template<QuantitySpec Child, QuantitySpec Parent>
|
||||||
|
[[nodiscard]] consteval auto is_child_of(Child ch, Parent);
|
||||||
|
|
||||||
template<auto To, auto From>
|
template<auto To, auto From>
|
||||||
concept NestedQuantityKindSpecOf =
|
concept NestedQuantityKindSpecOf =
|
||||||
QuantitySpec<decltype(From)> && QuantitySpec<decltype(To)> && get_kind(From) != get_kind(To) &&
|
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_)>>;
|
decltype(is_child_of(To, get_kind(From)._quantity_spec_))::value;
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
MP_UNITS_EXPORT template<typename T, auto QS>
|
MP_UNITS_EXPORT template<typename T, auto QS>
|
||||||
concept QuantitySpecOf =
|
concept QuantitySpecOf =
|
||||||
|
@ -85,7 +85,7 @@ static_assert(!Dimension<int>);
|
|||||||
// TODO add tests
|
// TODO add tests
|
||||||
|
|
||||||
// QuantitySpec
|
// 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::length>);
|
||||||
static_assert(QuantitySpec<struct isq::radius>);
|
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(isq::length / isq::time)>);
|
||||||
static_assert(QuantitySpec<decltype(pow<2>(isq::length))>);
|
static_assert(QuantitySpec<decltype(pow<2>(isq::length))>);
|
||||||
static_assert(QuantitySpec<struct dimensionless>);
|
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<struct isq::dim_length>);
|
||||||
static_assert(!QuantitySpec<int>);
|
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(isq::length / isq::time)>);
|
||||||
static_assert(!detail::NamedQuantitySpec<decltype(pow<2>(isq::length))>);
|
static_assert(!detail::NamedQuantitySpec<decltype(pow<2>(isq::length))>);
|
||||||
static_assert(detail::NamedQuantitySpec<struct dimensionless>);
|
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<struct isq::dim_length>);
|
||||||
static_assert(!detail::NamedQuantitySpec<int>);
|
static_assert(!detail::NamedQuantitySpec<int>);
|
||||||
|
|
||||||
// IntermediateDerivedQuantitySpec
|
// DerivedQuantitySpec
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<struct isq::length>);
|
static_assert(!detail::DerivedQuantitySpec<struct isq::length>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<struct isq::radius>);
|
static_assert(!detail::DerivedQuantitySpec<struct isq::radius>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<decltype(kind_of<isq::length>)>);
|
static_assert(!detail::DerivedQuantitySpec<decltype(kind_of<isq::length>)>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<struct isq::speed>);
|
static_assert(!detail::DerivedQuantitySpec<struct isq::speed>);
|
||||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(isq::length / isq::time)>);
|
static_assert(detail::DerivedQuantitySpec<decltype(isq::length / isq::time)>);
|
||||||
static_assert(detail::IntermediateDerivedQuantitySpec<decltype(pow<2>(isq::length))>);
|
static_assert(detail::DerivedQuantitySpec<decltype(pow<2>(isq::length))>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<struct dimensionless>);
|
static_assert(!detail::DerivedQuantitySpec<struct dimensionless>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<speed>);
|
static_assert(detail::DerivedQuantitySpec<std::remove_const_t<decltype(speed)>>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<struct isq::dim_length>);
|
static_assert(!detail::DerivedQuantitySpec<struct isq::dim_length>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<int>);
|
static_assert(!detail::DerivedQuantitySpec<int>);
|
||||||
|
|
||||||
// QuantityKindSpec
|
// QuantityKindSpec
|
||||||
static_assert(!detail::QuantityKindSpec<struct isq::length>);
|
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(isq::length / isq::time)>);
|
||||||
static_assert(!detail::QuantityKindSpec<decltype(pow<2>(isq::length))>);
|
static_assert(!detail::QuantityKindSpec<decltype(pow<2>(isq::length))>);
|
||||||
static_assert(!detail::QuantityKindSpec<struct dimensionless>);
|
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<struct isq::dim_length>);
|
||||||
static_assert(!detail::QuantityKindSpec<int>);
|
static_assert(!detail::QuantityKindSpec<int>);
|
||||||
|
|
||||||
|
@ -88,98 +88,98 @@ QUANTITY_SPEC_(kinetic_energy, mechanical_energy, mass* pow<2>(speed));
|
|||||||
// concepts verification
|
// concepts verification
|
||||||
static_assert(QuantitySpec<length_>);
|
static_assert(QuantitySpec<length_>);
|
||||||
static_assert(detail::NamedQuantitySpec<length_>);
|
static_assert(detail::NamedQuantitySpec<length_>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<length_>);
|
static_assert(!detail::DerivedQuantitySpec<length_>);
|
||||||
static_assert(!detail::QuantityKindSpec<length_>);
|
static_assert(!detail::QuantityKindSpec<length_>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<frequency_>);
|
static_assert(QuantitySpec<frequency_>);
|
||||||
static_assert(detail::NamedQuantitySpec<frequency_>);
|
static_assert(detail::NamedQuantitySpec<frequency_>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<frequency_>);
|
static_assert(!detail::DerivedQuantitySpec<frequency_>);
|
||||||
static_assert(!detail::QuantityKindSpec<frequency_>);
|
static_assert(!detail::QuantityKindSpec<frequency_>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<decltype(inverse(time))>);
|
static_assert(QuantitySpec<decltype(inverse(time))>);
|
||||||
static_assert(!detail::NamedQuantitySpec<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(!detail::QuantityKindSpec<decltype(inverse(time))>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<dimensionless_>);
|
static_assert(QuantitySpec<dimensionless_>);
|
||||||
static_assert(detail::NamedQuantitySpec<dimensionless_>);
|
static_assert(detail::NamedQuantitySpec<dimensionless_>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<dimensionless_>);
|
static_assert(!detail::DerivedQuantitySpec<dimensionless_>);
|
||||||
static_assert(!detail::QuantityKindSpec<dimensionless_>);
|
static_assert(!detail::QuantityKindSpec<dimensionless_>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<kind_of_<length_>>);
|
static_assert(QuantitySpec<kind_of_<length_>>);
|
||||||
static_assert(!detail::NamedQuantitySpec<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(detail::QuantityKindSpec<kind_of_<length_>>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<frequency_>);
|
static_assert(QuantitySpec<frequency_>);
|
||||||
static_assert(detail::NamedQuantitySpec<frequency_>);
|
static_assert(detail::NamedQuantitySpec<frequency_>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<frequency_>);
|
static_assert(!detail::DerivedQuantitySpec<frequency_>);
|
||||||
static_assert(!detail::QuantityKindSpec<frequency_>);
|
static_assert(!detail::QuantityKindSpec<frequency_>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<decltype(inverse(time))>);
|
static_assert(QuantitySpec<decltype(inverse(time))>);
|
||||||
static_assert(!detail::NamedQuantitySpec<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(!detail::QuantityKindSpec<decltype(inverse(time))>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<kind_of_<decltype(length / time)>>);
|
static_assert(QuantitySpec<kind_of_<decltype(length / time)>>);
|
||||||
static_assert(!detail::NamedQuantitySpec<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(detail::QuantityKindSpec<kind_of_<decltype(length / time)>>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<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::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(detail::QuantityKindSpec<decltype(kind_of<length> / kind_of<time>)>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<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::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(detail::QuantityKindSpec<decltype(kind_of<length> * kind_of<time>)>);
|
||||||
|
|
||||||
// dimensionless
|
// dimensionless
|
||||||
static_assert(QuantitySpec<dimensionless_>);
|
static_assert(QuantitySpec<dimensionless_>);
|
||||||
static_assert(detail::NamedQuantitySpec<dimensionless_>);
|
static_assert(detail::NamedQuantitySpec<dimensionless_>);
|
||||||
static_assert(!detail::IntermediateDerivedQuantitySpec<dimensionless_>);
|
static_assert(!detail::DerivedQuantitySpec<dimensionless_>);
|
||||||
static_assert(!detail::QuantityKindSpec<dimensionless_>);
|
static_assert(!detail::QuantityKindSpec<dimensionless_>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<decltype(length / length)>);
|
static_assert(QuantitySpec<decltype(length / length)>);
|
||||||
static_assert(detail::NamedQuantitySpec<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(!detail::QuantityKindSpec<decltype(length / length)>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<decltype(width / length)>);
|
static_assert(QuantitySpec<decltype(width / length)>);
|
||||||
static_assert(!detail::NamedQuantitySpec<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(!detail::QuantityKindSpec<decltype(width / length)>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<decltype(kind_of<length> / kind_of<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::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(detail::QuantityKindSpec<decltype(kind_of<length> / kind_of<length>)>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<decltype(kind_of<length> / length)>);
|
static_assert(QuantitySpec<decltype(kind_of<length> / length)>);
|
||||||
static_assert(detail::NamedQuantitySpec<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(!detail::QuantityKindSpec<decltype(kind_of<length> / length)>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<decltype(length / kind_of<length>)>);
|
static_assert(QuantitySpec<decltype(length / kind_of<length>)>);
|
||||||
static_assert(detail::NamedQuantitySpec<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(!detail::QuantityKindSpec<decltype(length / kind_of<length>)>);
|
||||||
|
|
||||||
static_assert(QuantitySpec<decltype(width / kind_of<length>)>);
|
static_assert(QuantitySpec<decltype(width / kind_of<length>)>);
|
||||||
static_assert(!detail::NamedQuantitySpec<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>)>);
|
static_assert(!detail::QuantityKindSpec<decltype(width / kind_of<length>)>);
|
||||||
|
|
||||||
// length
|
// length
|
||||||
static_assert(QuantitySpec<decltype(speed * time)>);
|
static_assert(QuantitySpec<decltype(speed * time)>);
|
||||||
static_assert(!detail::NamedQuantitySpec<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
|
// derived QuantitySpec expression template syntax verification
|
||||||
static_assert(!detail::NamedQuantitySpec<decltype(speed * time)>);
|
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<dimensionless * time, time_>);
|
||||||
static_assert(is_of_type<time * dimensionless, time_>);
|
static_assert(is_of_type<time * dimensionless, time_>);
|
||||||
|
@ -32,14 +32,14 @@ inline constexpr bool is_of_type = std::is_same_v<MP_UNITS_REMOVE_CONST(decltype
|
|||||||
// NOLINTBEGIN(cppcoreguidelines-macro-usage)
|
// NOLINTBEGIN(cppcoreguidelines-macro-usage)
|
||||||
#ifdef MP_UNITS_API_NO_CRTP
|
#ifdef MP_UNITS_API_NO_CRTP
|
||||||
|
|
||||||
#define QUANTITY_SPEC_(name, ...) \
|
#define QUANTITY_SPEC_(name, ...) \
|
||||||
inline constexpr struct name##_ : quantity_spec<__VA_ARGS__> { \
|
inline constexpr struct name##_ final : quantity_spec<__VA_ARGS__> { \
|
||||||
} name
|
} name
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define QUANTITY_SPEC_(name, ...) \
|
#define QUANTITY_SPEC_(name, ...) \
|
||||||
inline constexpr struct name##_ : quantity_spec<name##_, __VA_ARGS__> { \
|
inline constexpr struct name##_ final : quantity_spec<name##_, __VA_ARGS__> { \
|
||||||
} name
|
} name
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user