refactor: reference specifiers are now variable templates

This commit is contained in:
Mateusz Pusz
2024-06-20 09:20:33 +02:00
parent 1eac5a923b
commit 4b46be7604
18 changed files with 120 additions and 125 deletions

View File

@ -238,7 +238,7 @@ This introduces an additional type-safety.
using namespace mp_units::si::unit_symbols;
using namespace mp_units::usc::unit_symbols;
quantity_point temp = 20. * absolute(deg_C);
quantity_point temp = 20. * absolute<deg_C>;
std::println("Temperature: {} ({})",
temp.quantity_from_zero(),
temp.in(deg_F).quantity_from_zero());
@ -259,7 +259,7 @@ This introduces an additional type-safety.
using namespace mp_units::si::unit_symbols;
using namespace mp_units::usc::unit_symbols;
quantity_point temp = 20. * absolute(deg_C);
quantity_point temp = 20. * absolute<deg_C>;
std::println("Temperature: {} ({})",
temp.quantity_from_zero(),
temp.in(deg_F).quantity_from_zero());

View File

@ -378,5 +378,5 @@ For example:
the previous example:
```cpp
constexpr auto room_reference_temperature = ice_point + isq::Celsius_temperature(21 * delta(deg_C));
constexpr auto room_reference_temperature = ice_point + isq::Celsius_temperature(21 * delta<deg_C>);
```

View File

@ -83,10 +83,10 @@ We can create a `quantity` by passing a delta quantity reference to either:
// quantity q2(42, si::kelvin); // Compile-time error
// quantity q3(42, si::degree_Celsius); // Compile-time error
// quantity q4(42, usc::degree_Fahrenheit); // Compile-time error
quantity q5(42, delta(si::metre));
quantity q6(42, delta(si::kelvin));
quantity q7(42, delta(si::degree_Celsius));
quantity q8(42, delta(usc::degree_Fahrenheit));
quantity q5(42, delta<si::metre>);
quantity q6(42, delta<si::kelvin>);
quantity q7(42, delta<si::degree_Celsius>);
quantity q8(42, delta<usc::degree_Fahrenheit>);
```
- multiply syntax:
@ -96,10 +96,10 @@ We can create a `quantity` by passing a delta quantity reference to either:
// quantity q2 = 42 * K; // Compile-time error
// quantity q3 = 42 * deg_C; // Compile-time error
// quantity q4 = 42 * deg_F; // Compile-time error
quantity q5 = 42 * delta(m);
quantity q6 = 42 * delta(K);
quantity q7 = 42 * delta(deg_C);
quantity q8 = 42 * delta(deg_F);
quantity q5 = 42 * delta<m>;
quantity q6 = 42 * delta<K>;
quantity q7 = 42 * delta<deg_C>;
quantity q8 = 42 * delta<deg_F>;
```
!!! note
@ -109,9 +109,9 @@ We can create a `quantity` by passing a delta quantity reference to either:
for example, the below are ill-formed:
```cpp
void foo(quantity<delta(si::degree_Celsius)> temp); // ill-formed
quantity<N * m / (delta(deg_C) * mol)> specific_heat_capacity; // ill-formed
quantity R = 8.314 * N * m / (delta(deg_C) * mol); // ill-formed
void foo(quantity<delta<si::degree_Celsius>> temp); // ill-formed
quantity<N * m / (delta<deg_C> * mol)> specific_heat_capacity; // ill-formed
quantity R = 8.314 * N * m / (delta<deg_C> * mol); // ill-formed
```
## _Point_ is modeled by `quantity_point` and `PointOrigin`
@ -160,9 +160,9 @@ so they need a special qualification:
// quantity_point qp1 = 42 * m; // Compile-time error
// quantity_point qp2 = 42 * K; // Compile-time error
// quantity_point qp3 = 42 * deg_C; // Compile-time error
quantity_point qp4 = 42 * absolute(m);
quantity_point qp5 = 42 * absolute(K);
quantity_point qp6 = 42 * absolute(deg_C);
quantity_point qp4 = 42 * absolute<m>;
quantity_point qp5 = 42 * absolute<K>;
quantity_point qp6 = 42 * absolute<deg_C>;
```
!!! tip
@ -180,8 +180,8 @@ for this domain.
![affine_space_1](affine_space_1.svg){style="width:80%;display: block;margin: 0 auto;"}
```cpp
quantity_point<isq::distance[si::metre]> qp1 = 100 * absolute(m);
quantity_point<isq::distance[si::metre]> qp2 = 120 * absolute(m);
quantity_point<isq::distance[si::metre]> qp1 = 100 * absolute<m>;
quantity_point<isq::distance[si::metre]> qp2 = 120 * absolute<m>;
assert(qp1.quantity_from_zero() == 100 * m);
assert(qp2.quantity_from_zero() == 120 * m);
@ -231,7 +231,7 @@ origin.
inline constexpr struct origin final : absolute_point_origin<isq::distance> {} origin;
// quantity_point<si::metre, origin> qp1{100 * m}; // Compile-time error
// quantity_point<si::metre, origin> qp2 = 120 * absolute(m); // Compile-time error
// quantity_point<si::metre, origin> qp2 = 120 * absolute<m>; // Compile-time error
quantity_point<si::metre, origin> qp1 = origin + 100 * m;
quantity_point<si::metre, origin> qp2 = 120 * m + origin;
@ -443,7 +443,7 @@ namespace si {
inline constexpr struct absolute_zero final : absolute_point_origin<isq::thermodynamic_temperature> {} absolute_zero;
inline constexpr auto zeroth_kelvin = absolute_zero;
inline constexpr struct ice_point final : relative_point_origin<273'150 * absolute(milli<kelvin>)}> {} ice_point;
inline constexpr struct ice_point final : relative_point_origin<273'150 * absolute<milli<kelvin>>}> {} ice_point;
inline constexpr auto zeroth_degree_Celsius = ice_point;
}
@ -451,7 +451,7 @@ inline constexpr auto zeroth_degree_Celsius = ice_point;
namespace usc {
inline constexpr struct zeroth_degree_Fahrenheit final :
relative_point_origin<-32 * absolute(mag_ratio<5, 9> * si::degree_Celsius)> {} zeroth_degree_Fahrenheit;
relative_point_origin<-32 * absolute<mag_ratio<5, 9> * si::degree_Celsius>> {} zeroth_degree_Fahrenheit;
}
```
@ -500,28 +500,28 @@ choose from here. Depending on our needs or tastes, we can:
- be explicit about the unit and origin:
```cpp
quantity_point<si::degree_Celsius, si::zeroth_degree_Celsius> q1 = si::zeroth_degree_Celsius + 20.5 * delta(deg_C);
quantity_point<si::degree_Celsius, si::zeroth_degree_Celsius> q2 = {20.5 * delta(deg_C), si::zeroth_degree_Celsius};
quantity_point<si::degree_Celsius, si::zeroth_degree_Celsius> q3{20.5 * delta(deg_C)};
quantity_point<si::degree_Celsius, si::zeroth_degree_Celsius> q4 = 20.5 * absolute(deg_C);
quantity_point<si::degree_Celsius, si::zeroth_degree_Celsius> q1 = si::zeroth_degree_Celsius + 20.5 * delta<deg_C>;
quantity_point<si::degree_Celsius, si::zeroth_degree_Celsius> q2 = {20.5 * delta<deg_C>, si::zeroth_degree_Celsius};
quantity_point<si::degree_Celsius, si::zeroth_degree_Celsius> q3{20.5 * delta<deg_C>};
quantity_point<si::degree_Celsius, si::zeroth_degree_Celsius> q4 = 20.5 * absolute<deg_C>;
```
- specify a unit and use its zeroth point origin implicitly:
```cpp
quantity_point<si::degree_Celsius> q5 = si::zeroth_degree_Celsius + 20.5 * delta(deg_C);
quantity_point<si::degree_Celsius> q6 = {20.5 * delta(deg_C), si::zeroth_degree_Celsius};
quantity_point<si::degree_Celsius> q7{20.5 * delta(deg_C)};
quantity_point<si::degree_Celsius> q8 = 20.5 * absolute(deg_C);
quantity_point<si::degree_Celsius> q5 = si::zeroth_degree_Celsius + 20.5 * delta<deg_C>;
quantity_point<si::degree_Celsius> q6 = {20.5 * delta<deg_C>, si::zeroth_degree_Celsius};
quantity_point<si::degree_Celsius> q7{20.5 * delta<deg_C>};
quantity_point<si::degree_Celsius> q8 = 20.5 * absolute<deg_C>;
```
- benefit from CTAD:
```cpp
quantity_point q9 = si::zeroth_degree_Celsius + 20.5 * delta(deg_C);
quantity_point q10 = {20.5 * delta(deg_C), si::zeroth_degree_Celsius};
quantity_point q11{20.5 * delta(deg_C)};
quantity_point q12 = 20.5 * absolute(deg_C);
quantity_point q9 = si::zeroth_degree_Celsius + 20.5 * delta<deg_C>;
quantity_point q10 = {20.5 * delta<deg_C>, si::zeroth_degree_Celsius};
quantity_point q11{20.5 * delta<deg_C>};
quantity_point q12 = 20.5 * absolute<deg_C>;
```
In all of the above cases, we end up with the `quantity_point` of the same type and value.
@ -532,10 +532,10 @@ the following way:
![affine_space_6](affine_space_6.svg){style="width:80%;display: block;margin: 0 auto;"}
```cpp
constexpr struct room_reference_temp final : relative_point_origin<21 * absolute(deg_C)> {} room_reference_temp;
constexpr struct room_reference_temp final : relative_point_origin<21 * absolute<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 * delta(deg_C));
constexpr auto step_delta = isq::Celsius_temperature(0.5 * delta<deg_C>);
constexpr int number_of_steps = 6;
room_temp room_ref{};

View File

@ -62,13 +62,13 @@ int main()
using estimate = kalman::system_state_estimate<qp>;
using state = estimate::state_type;
const quantity process_noise_variance = 0.0001 * delta(pow<2>(deg_C));
const estimate initial{state{qp{60. * delta(deg_C)}}, 100. * delta(deg_C)};
const std::array measurements = {qp{49.986 * delta(deg_C)}, qp{49.963 * delta(deg_C)}, qp{50.097 * delta(deg_C)},
qp{50.001 * delta(deg_C)}, qp{50.018 * delta(deg_C)}, qp{50.05 * delta(deg_C)},
qp{49.938 * delta(deg_C)}, qp{49.858 * delta(deg_C)}, qp{49.965 * delta(deg_C)},
qp{50.114 * delta(deg_C)}};
const quantity measurement_error = 0.1 * delta(deg_C);
const quantity process_noise_variance = 0.0001 * delta<pow<2>(deg_C)>;
const estimate initial{state{qp{60. * delta<deg_C>}}, 100. * delta<deg_C>};
const std::array measurements = {qp{49.986 * delta<deg_C>}, qp{49.963 * delta<deg_C>}, qp{50.097 * delta<deg_C>},
qp{50.001 * delta<deg_C>}, qp{50.018 * delta<deg_C>}, qp{50.05 * delta<deg_C>},
qp{49.938 * delta<deg_C>}, qp{49.858 * delta<deg_C>}, qp{49.965 * delta<deg_C>},
qp{50.114 * delta<deg_C>}};
const quantity measurement_error = 0.1 * delta<deg_C>;
const quantity measurement_variance = pow<2>(measurement_error);
auto predict = [=](const estimate& current) {

View File

@ -62,13 +62,13 @@ int main()
using estimate = kalman::system_state_estimate<qp>;
using state = estimate::state_type;
const quantity process_noise_variance = 0.0001 * delta(pow<2>(deg_C));
const estimate initial{state{qp{10. * delta(deg_C)}}, 100. * delta(deg_C)};
const std::array measurements = {qp{50.486 * delta(deg_C)}, qp{50.963 * delta(deg_C)}, qp{51.597 * delta(deg_C)},
qp{52.001 * delta(deg_C)}, qp{52.518 * delta(deg_C)}, qp{53.05 * delta(deg_C)},
qp{53.438 * delta(deg_C)}, qp{53.858 * delta(deg_C)}, qp{54.465 * delta(deg_C)},
qp{55.114 * delta(deg_C)}};
const quantity measurement_error = 0.1 * delta(deg_C);
const quantity process_noise_variance = 0.0001 * delta<pow<2>(deg_C)>;
const estimate initial{state{qp{10. * delta<deg_C>}}, 100. * delta<deg_C>};
const std::array measurements = {qp{50.486 * delta<deg_C>}, qp{50.963 * delta<deg_C>}, qp{51.597 * delta<deg_C>},
qp{52.001 * delta<deg_C>}, qp{52.518 * delta<deg_C>}, qp{53.05 * delta<deg_C>},
qp{53.438 * delta<deg_C>}, qp{53.858 * delta<deg_C>}, qp{54.465 * delta<deg_C>},
qp{55.114 * delta<deg_C>}};
const quantity measurement_error = 0.1 * delta<deg_C>;
const quantity measurement_variance = pow<2>(measurement_error);
auto predict = [=](const estimate& current) {

View File

@ -62,13 +62,13 @@ int main()
using estimate = kalman::system_state_estimate<qp>;
using state = estimate::state_type;
const quantity process_noise_variance = 0.15 * delta(pow<2>(deg_C));
const estimate initial{state{qp{10. * delta(deg_C)}}, 100. * delta(deg_C)};
const std::array measurements = {qp{50.486 * delta(deg_C)}, qp{50.963 * delta(deg_C)}, qp{51.597 * delta(deg_C)},
qp{52.001 * delta(deg_C)}, qp{52.518 * delta(deg_C)}, qp{53.05 * delta(deg_C)},
qp{53.438 * delta(deg_C)}, qp{53.858 * delta(deg_C)}, qp{54.465 * delta(deg_C)},
qp{55.114 * delta(deg_C)}};
const quantity measurement_error = 0.1 * delta(deg_C);
const quantity process_noise_variance = 0.15 * delta<pow<2>(deg_C)>;
const estimate initial{state{qp{10. * delta<deg_C>}}, 100. * delta<deg_C>};
const std::array measurements = {qp{50.486 * delta<deg_C>}, qp{50.963 * delta<deg_C>}, qp{51.597 * delta<deg_C>},
qp{52.001 * delta<deg_C>}, qp{52.518 * delta<deg_C>}, qp{53.05 * delta<deg_C>},
qp{53.438 * delta<deg_C>}, qp{53.858 * delta<deg_C>}, qp{54.465 * delta<deg_C>},
qp{55.114 * delta<deg_C>}};
const quantity measurement_error = 0.1 * delta<deg_C>;
const quantity measurement_variance = pow<2>(measurement_error);
auto predict = [=](const estimate& current) {

View File

@ -84,7 +84,7 @@ int main()
const auto t3 = std::make_tuple(isq::energy(q3 * h), isq::wavenumber(q3 / c), q3,
isq::thermodynamic_temperature(q3 * h / kb), isq::wavelength(c / q3));
const auto q4 = isq::thermodynamic_temperature(1. * delta(K));
const auto q4 = isq::thermodynamic_temperature(1. * delta<K>);
const auto t4 = std::make_tuple(isq::energy(q4 * kb), isq::wavenumber(q4 * kb / (h * c)), isq::frequency(q4 * kb / h),
q4, isq::wavelength(h * c / (q4 * kb)));

View File

@ -97,7 +97,7 @@ template<Quantity To, typename From>
if constexpr (q_unit == To::unit) {
// no scaling of the number needed
return {static_cast<MP_UNITS_TYPENAME To::rep>(std::forward<From>(q).numerical_value_is_an_implementation_detail_),
delta(To::reference)}; // this is the only (and recommended) way to do
delta<To::reference>}; // this is the only (and recommended) way to do
// a truncating conversion on a number, so we are
// using static_cast to suppress all the compiler
// warnings on conversions
@ -108,13 +108,13 @@ template<Quantity To, typename From>
// this results in great assembly
auto res = static_cast<MP_UNITS_TYPENAME To::rep>(
static_cast<traits::c_type>(q.numerical_value_is_an_implementation_detail_) * traits::ratio);
return {res, delta(To::reference)};
return {res, delta<To::reference>};
} else {
// this is slower but allows conversions like 2000 m -> 2 km without loosing data
auto res = static_cast<MP_UNITS_TYPENAME To::rep>(
static_cast<traits::c_type>(q.numerical_value_is_an_implementation_detail_) * traits::num_mult /
traits::den_mult * traits::irr_mult);
return {res, delta(To::reference)};
return {res, delta<To::reference>};
}
}
}

View File

@ -123,25 +123,25 @@ public:
[[nodiscard]] static constexpr quantity zero() noexcept
requires requires { quantity_values<rep>::zero(); }
{
return {quantity_values<rep>::zero(), delta(R)};
return {quantity_values<rep>::zero(), delta<R>};
}
[[nodiscard]] static constexpr quantity one() noexcept
requires requires { quantity_values<rep>::one(); }
{
return {quantity_values<rep>::one(), delta(R)};
return {quantity_values<rep>::one(), delta<R>};
}
[[nodiscard]] static constexpr quantity min() noexcept
requires requires { quantity_values<rep>::min(); }
{
return {quantity_values<rep>::min(), delta(R)};
return {quantity_values<rep>::min(), delta<R>};
}
[[nodiscard]] static constexpr quantity max() noexcept
requires requires { quantity_values<rep>::max(); }
{
return {quantity_values<rep>::max(), delta(R)};
return {quantity_values<rep>::max(), delta<R>};
}
// construction, assignment, destruction
@ -180,7 +180,7 @@ public:
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
!std::convertible_to<typename quantity_like_traits<Q>::rep, Rep>) quantity(const Q& q) :
quantity(::mp_units::quantity{quantity_like_traits<Q>::to_numerical_value(q).value,
delta(quantity_like_traits<Q>::reference)})
delta<quantity_like_traits<Q>::reference>})
{
}
@ -274,7 +274,7 @@ public:
} -> std::common_with<rep>;
}
{
return ::mp_units::quantity{+numerical_value_is_an_implementation_detail_, delta(reference)};
return ::mp_units::quantity{+numerical_value_is_an_implementation_detail_, delta<reference>};
}
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto operator-() const
@ -284,7 +284,7 @@ public:
} -> std::common_with<rep>;
}
{
return ::mp_units::quantity{-numerical_value_is_an_implementation_detail_, delta(reference)};
return ::mp_units::quantity{-numerical_value_is_an_implementation_detail_, delta<reference>};
}
template<typename Q>
@ -306,7 +306,7 @@ public:
} -> std::common_with<rep>;
}
{
return ::mp_units::quantity{numerical_value_is_an_implementation_detail_++, delta(reference)};
return ::mp_units::quantity{numerical_value_is_an_implementation_detail_++, delta<reference>};
}
template<typename Q>
@ -328,7 +328,7 @@ public:
} -> std::common_with<rep>;
}
{
return ::mp_units::quantity{numerical_value_is_an_implementation_detail_--, delta(reference)};
return ::mp_units::quantity{numerical_value_is_an_implementation_detail_--, delta<reference>};
}
// compound assignment operators
@ -445,7 +445,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
const ret ret_lhs(lhs);
const ret ret_rhs(rhs);
return quantity{ret_lhs.numerical_value_ref_in(ret::unit) + ret_rhs.numerical_value_ref_in(ret::unit),
delta(ret::reference)};
delta<ret::reference>};
}
template<auto R1, typename Rep1, auto R2, typename Rep2>
@ -456,7 +456,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
const ret ret_lhs(lhs);
const ret ret_rhs(rhs);
return quantity{ret_lhs.numerical_value_ref_in(ret::unit) - ret_rhs.numerical_value_ref_in(ret::unit),
delta(ret::reference)};
delta<ret::reference>};
}
template<auto R1, typename Rep1, auto R2, typename Rep2>
@ -469,14 +469,14 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
const ret ret_lhs(lhs);
const ret ret_rhs(rhs);
return quantity{ret_lhs.numerical_value_ref_in(ret::unit) % ret_rhs.numerical_value_ref_in(ret::unit),
delta(ret::reference)};
delta<ret::reference>};
}
template<auto R1, typename Rep1, auto R2, typename Rep2>
requires detail::InvocableQuantities<std::multiplies<>, quantity<R1, Rep1>, quantity<R2, Rep2>>
[[nodiscard]] constexpr Quantity auto operator*(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
{
return quantity{lhs.numerical_value_ref_in(get_unit(R1)) * rhs.numerical_value_ref_in(get_unit(R2)), delta(R1 * R2)};
return quantity{lhs.numerical_value_ref_in(get_unit(R1)) * rhs.numerical_value_ref_in(get_unit(R2)), delta<R1 * R2>};
}
template<auto R, typename Rep, typename Value>
@ -484,7 +484,7 @@ template<auto R, typename Rep, typename Value>
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, Rep, const Value&>
[[nodiscard]] constexpr QuantityOf<get_quantity_spec(R)> auto operator*(const quantity<R, Rep>& q, const Value& v)
{
return quantity{q.numerical_value_ref_in(get_unit(R)) * v, delta(R)};
return quantity{q.numerical_value_ref_in(get_unit(R)) * v, delta<R>};
}
template<typename Value, auto R, typename Rep>
@ -492,7 +492,7 @@ template<typename Value, auto R, typename Rep>
detail::InvokeResultOf<get_quantity_spec(R).character, std::multiplies<>, const Value&, Rep>
[[nodiscard]] constexpr QuantityOf<get_quantity_spec(R)> auto operator*(const Value& v, const quantity<R, Rep>& q)
{
return quantity{v * q.numerical_value_ref_in(get_unit(R)), delta(R)};
return quantity{v * q.numerical_value_ref_in(get_unit(R)), delta<R>};
}
template<auto R1, typename Rep1, auto R2, typename Rep2>
@ -500,7 +500,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
[[nodiscard]] constexpr Quantity auto operator/(const quantity<R1, Rep1>& lhs, const quantity<R2, Rep2>& rhs)
{
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
return quantity{lhs.numerical_value_ref_in(get_unit(R1)) / rhs.numerical_value_ref_in(get_unit(R2)), delta(R1 / R2)};
return quantity{lhs.numerical_value_ref_in(get_unit(R1)) / rhs.numerical_value_ref_in(get_unit(R2)), delta<R1 / R2>};
}
template<auto R, typename Rep, typename Value>
@ -509,7 +509,7 @@ template<auto R, typename Rep, typename Value>
[[nodiscard]] constexpr QuantityOf<get_quantity_spec(R)> auto operator/(const quantity<R, Rep>& q, const Value& v)
{
MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero());
return quantity{q.numerical_value_ref_in(get_unit(R)) / v, delta(R)};
return quantity{q.numerical_value_ref_in(get_unit(R)) / v, delta<R>};
}
template<typename Value, auto R, typename Rep>
@ -518,7 +518,7 @@ template<typename Value, auto R, typename Rep>
[[nodiscard]] constexpr QuantityOf<inverse(get_quantity_spec(R))> auto operator/(const Value& v,
const quantity<R, Rep>& q)
{
return quantity{v / q.numerical_value_ref_in(get_unit(R)), delta(::mp_units::one / R)};
return quantity{v / q.numerical_value_ref_in(get_unit(R)), delta<::mp_units::one / R>};
}
template<auto R1, typename Rep1, auto R2, typename Rep2>

View File

@ -57,7 +57,7 @@ template<QuantitySpec auto ToQS, typename Q>
[[nodiscard]] constexpr Quantity auto quantity_cast(Q&& q)
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
delta(make_reference(ToQS, std::remove_reference_t<Q>::unit))};
delta<make_reference(ToQS, std::remove_reference_t<Q>::unit)>};
}
/**

View File

@ -129,7 +129,7 @@ struct quantity_spec_interface {
(explicitly_convertible(std::remove_reference_t<Q>::quantity_spec, self))
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
delta(detail::make_reference(self, std::remove_cvref_t<Q>::unit))};
delta<detail::make_reference(self, std::remove_cvref_t<Q>::unit)>};
}
#else
template<typename Self_ = Self, UnitOf<Self_{}> U>
@ -144,7 +144,7 @@ struct quantity_spec_interface {
[[nodiscard]] constexpr Quantity auto operator()(Q&& q) const
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
delta(detail::make_reference(Self{}, std::remove_cvref_t<Q>::unit))};
delta<detail::make_reference(Self{}, std::remove_cvref_t<Q>::unit)>};
}
#endif
};
@ -341,7 +341,7 @@ struct quantity_spec<Self, QS, Args...> : detail::propagate_equation<QS>, detail
[[nodiscard]] constexpr Quantity auto operator()(Q&& q) const
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
delta(detail::make_reference(Self{}, std::remove_cvref_t<Q>::unit))};
delta<detail::make_reference(Self{}, std::remove_cvref_t<Q>::unit)>};
}
#endif
};

View File

@ -44,8 +44,8 @@ template<typename R>
requires DeltaReference<R> || AbsoluteReference<R>
[[nodiscard]] consteval Reference auto get_original_reference(R r)
{
if constexpr (requires { typename R::_type_; })
return typename R::_type_{};
if constexpr (requires { R::_original_reference_; })
return R::_original_reference_;
else
return r;
}
@ -195,7 +195,7 @@ template<typename Rep, DeltaReference R>
[[nodiscard]] constexpr quantity<inverse(detail::get_original_reference(R{})), std::remove_cvref_t<Rep>> operator/(
Rep&& lhs, R)
{
return quantity{std::forward<Rep>(lhs), delta(inverse(detail::get_original_reference(R{})))};
return quantity{std::forward<Rep>(lhs), delta<inverse(detail::get_original_reference(R{}))>};
}
template<typename Rep, AbsoluteReference R>
@ -205,7 +205,7 @@ template<typename Rep, AbsoluteReference R>
std::remove_cvref_t<Rep>>
operator*(Rep&& lhs, R)
{
return quantity_point{std::forward<Rep>(lhs) * delta(detail::get_original_reference(R{}))};
return quantity_point{std::forward<Rep>(lhs) * delta<detail::get_original_reference(R{})>};
}
template<typename Rep, AbsoluteReference R>
@ -215,7 +215,7 @@ template<typename Rep, AbsoluteReference R>
std::remove_cvref_t<Rep>>
operator/(Rep&& lhs, R)
{
return quantity_point{std::forward<Rep>(lhs) * delta(inverse(detail::get_original_reference(R{})))};
return quantity_point{std::forward<Rep>(lhs) * delta<inverse(detail::get_original_reference(R{}))>};
}
template<Reference R, typename Rep>
@ -233,7 +233,7 @@ template<typename Q, Reference R>
[[nodiscard]] constexpr Quantity auto operator*(Q&& q, R)
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
delta(std::remove_cvref_t<Q>::reference * R{})};
delta<std::remove_cvref_t<Q>::reference * R{}>};
}
template<typename Q, Reference R>
@ -241,7 +241,7 @@ template<typename Q, Reference R>
[[nodiscard]] constexpr Quantity auto operator/(Q&& q, R)
{
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
delta(std::remove_cvref_t<Q>::reference / R{})};
delta<std::remove_cvref_t<Q>::reference / R{}>};
}
template<Reference R, typename Q>

View File

@ -80,27 +80,22 @@ concept ReferenceOf = Reference<T> && QuantitySpecOf<decltype(get_quantity_spec(
MP_UNITS_EXPORT_END
// reference specifiers
template<Reference R>
struct relative_ final {
using _type_ = R;
static constexpr Reference auto _original_reference_ = R{};
};
template<Reference R>
struct absolute_ final {
using _type_ = R;
static constexpr Reference auto _original_reference_ = R{};
};
template<Reference R>
MP_UNITS_EXPORT [[nodiscard]] consteval relative_<R> delta(R)
{
return {};
}
template<Reference auto R>
MP_UNITS_EXPORT inline constexpr relative_<MP_UNITS_REMOVE_CONST(decltype(R))> delta{};
template<Reference R>
MP_UNITS_EXPORT [[nodiscard]] consteval absolute_<R> absolute(R)
{
return {};
}
template<Reference auto R>
MP_UNITS_EXPORT inline constexpr absolute_<MP_UNITS_REMOVE_CONST(decltype(R))> absolute{};
template<typename T>
MP_UNITS_EXPORT concept DeltaReference =

View File

@ -115,7 +115,7 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
{
using std::exp;
return value_cast<get_unit(R)>(
quantity{static_cast<Rep>(exp(q.force_numerical_value_in(q.unit))), delta(detail::clone_reference_with<one>(R))});
quantity{static_cast<Rep>(exp(q.force_numerical_value_in(q.unit))), delta<detail::clone_reference_with<one>(R)>});
}
/**
@ -236,7 +236,7 @@ template<auto R, auto S, auto T, typename Rep1, typename Rep2, typename Rep3>
using std::fma;
return quantity{
fma(a.numerical_value_ref_in(a.unit), x.numerical_value_ref_in(x.unit), b.numerical_value_ref_in(b.unit)),
delta(common_reference(R * S, T))};
delta<common_reference(R * S, T)>};
}
/**
@ -260,7 +260,7 @@ template<auto R, auto S, auto T, auto Origin, typename Rep1, typename Rep2, type
using std::fma;
return Origin + quantity{fma(a.numerical_value_ref_in(a.unit), x.numerical_value_ref_in(x.unit),
b.quantity_ref_from(b.point_origin).numerical_value_ref_in(b.unit)),
delta(common_reference(R * S, T))};
delta<common_reference(R * S, T)>};
}
/**
@ -277,7 +277,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
constexpr auto ref = common_reference(R1, R2);
constexpr auto unit = get_unit(ref);
using std::fmod;
return quantity{fmod(x.numerical_value_in(unit), y.numerical_value_in(unit)), delta(ref)};
return quantity{fmod(x.numerical_value_in(unit), y.numerical_value_in(unit)), delta<ref>};
}
/**
@ -294,7 +294,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
constexpr auto ref = common_reference(R1, R2);
constexpr auto unit = get_unit(ref);
using std::remainder;
return quantity{remainder(x.numerical_value_in(unit), y.numerical_value_in(unit)), delta(ref)};
return quantity{remainder(x.numerical_value_in(unit), y.numerical_value_in(unit)), delta<ref>};
}
@ -339,7 +339,7 @@ template<Unit auto To, auto R, typename Rep>
return {static_cast<Rep>(floor(q.numerical_value_ref_in(q.unit))), detail::clone_reference_with<To>(R)};
} else {
return handle_signed_results(
quantity{static_cast<Rep>(floor(q.force_numerical_value_in(To))), delta(detail::clone_reference_with<To>(R))});
quantity{static_cast<Rep>(floor(q.force_numerical_value_in(To))), delta<detail::clone_reference_with<To>(R)>});
}
} else {
if constexpr (To == get_unit(R)) {
@ -376,7 +376,7 @@ template<Unit auto To, auto R, typename Rep>
return {static_cast<Rep>(ceil(q.numerical_value_ref_in(q.unit))), detail::clone_reference_with<To>(R)};
} else {
return handle_signed_results(
quantity{static_cast<Rep>(ceil(q.force_numerical_value_in(To))), delta(detail::clone_reference_with<To>(R))});
quantity{static_cast<Rep>(ceil(q.force_numerical_value_in(To))), delta<detail::clone_reference_with<To>(R)>});
}
} else {
if constexpr (To == get_unit(R)) {
@ -456,7 +456,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
constexpr auto ref = common_reference(R1, R2);
constexpr auto unit = get_unit(ref);
using std::hypot;
return quantity{hypot(x.numerical_value_in(unit), y.numerical_value_in(unit)), delta(ref)};
return quantity{hypot(x.numerical_value_in(unit), y.numerical_value_in(unit)), delta<ref>};
}
/**
@ -475,7 +475,7 @@ template<auto R1, typename Rep1, auto R2, typename Rep2, auto R3, typename Rep3>
constexpr auto unit = get_unit(ref);
using std::hypot;
return quantity{hypot(x.numerical_value_in(unit), y.numerical_value_in(unit), z.numerical_value_in(unit)),
delta(ref)};
delta<ref>};
}
} // namespace mp_units

View File

@ -77,7 +77,7 @@ inline constexpr struct weber final : named_unit<"Wb", volt * second> {} weber;
inline constexpr struct tesla final : named_unit<"T", weber / square(metre)> {} tesla;
inline constexpr struct henry final : named_unit<"H", weber / ampere> {} henry;
inline constexpr struct ice_point final : relative_point_origin<273'150 * absolute(milli<kelvin>)> {} ice_point;
inline constexpr struct ice_point final : relative_point_origin<273'150 * absolute<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;

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;
// https://en.wikipedia.org/wiki/United_States_customary_units#Temperature
inline constexpr struct zeroth_degree_Fahrenheit final : relative_point_origin<-32 * absolute(mag_ratio<5, 9> * si::degree_Celsius)> {} zeroth_degree_Fahrenheit;
inline constexpr struct zeroth_degree_Fahrenheit final : relative_point_origin<-32 * absolute<mag_ratio<5, 9> * si::degree_Celsius>> {} zeroth_degree_Fahrenheit;
inline constexpr struct degree_Fahrenheit final : named_unit<symbol_text{u8"°F", "`F"}, mag_ratio<5, 9> * si::degree_Celsius, zeroth_degree_Fahrenheit> {} degree_Fahrenheit;
// clang-format on

View File

@ -801,12 +801,12 @@ static_assert(
//////////////////////////////////
static_assert(quantity_point{42 * m}.quantity_from_zero() == 42 * m);
static_assert((42 * absolute(m)).quantity_from_zero() == 42 * m);
static_assert((42 * absolute<m>).quantity_from_zero() == 42 * m);
static_assert(quantity_point{isq::height(42 * m)}.quantity_from_zero() == 42 * m);
static_assert(quantity_point{20 * delta(deg_C)}.quantity_from_zero() == 20 * delta(deg_C));
static_assert((20 * absolute(deg_C)).quantity_from_zero() == 20 * delta(deg_C));
static_assert(quantity_point{20. * delta(deg_C)}.in(deg_F).quantity_from_zero() == 68 * delta(deg_F));
static_assert((20. * absolute(deg_C)).in(deg_F).quantity_from_zero() == 68 * delta(deg_F));
static_assert(quantity_point{20 * delta<deg_C>}.quantity_from_zero() == 20 * delta<deg_C>);
static_assert((20 * absolute<deg_C>).quantity_from_zero() == 20 * delta<deg_C>);
static_assert(quantity_point{20. * delta<deg_C>}.in(deg_F).quantity_from_zero() == 68 * delta<deg_F>);
static_assert((20. * absolute<deg_C>).in(deg_F).quantity_from_zero() == 68 * delta<deg_F>);
static_assert((mean_sea_level + 42 * m).quantity_from_zero() == 42 * m);
static_assert((ground_level + 42 * m).quantity_from_zero() == 84 * m);
@ -892,12 +892,12 @@ static_assert(std::is_same_v<std::remove_const_t<decltype(quantity_point{isq::he
static_assert(quantity_point{isq::height(123 * m)}.unit == si::metre);
static_assert(quantity_point{isq::height(123 * m)}.quantity_spec == isq::height);
static_assert(std::is_same_v<decltype(20 * absolute(deg_C))::rep, int>);
static_assert(std::is_same_v<std::remove_const_t<decltype((20 * absolute(deg_C)).point_origin)>, struct si::ice_point>);
static_assert(std::is_same_v<std::remove_const_t<decltype((20 * absolute(deg_C)).absolute_point_origin)>,
static_assert(std::is_same_v<decltype(20 * absolute<deg_C>)::rep, int>);
static_assert(std::is_same_v<std::remove_const_t<decltype((20 * absolute<deg_C>).point_origin)>, struct si::ice_point>);
static_assert(std::is_same_v<std::remove_const_t<decltype((20 * absolute<deg_C>).absolute_point_origin)>,
struct si::absolute_zero>);
static_assert((20 * absolute(deg_C)).unit == si::degree_Celsius);
static_assert((20 * absolute(deg_C)).quantity_spec == kind_of<isq::thermodynamic_temperature>);
static_assert((20 * absolute<deg_C>).unit == si::degree_Celsius);
static_assert((20 * absolute<deg_C>).quantity_spec == kind_of<isq::thermodynamic_temperature>);
#if MP_UNITS_HOSTED
using namespace std::chrono_literals;

View File

@ -126,7 +126,7 @@ static_assert(isq::mass(1 * lb_t) == isq::mass(12 * oz_t));
static_assert(isq::pressure(1'000 * inHg) == isq::pressure(3'386'389 * si::pascal));
// Temperature
static_assert(isq::thermodynamic_temperature(9 * delta(deg_F)) ==
isq::thermodynamic_temperature(5 * delta(si::degree_Celsius)));
static_assert(isq::thermodynamic_temperature(9 * delta<deg_F>) ==
isq::thermodynamic_temperature(5 * delta<si::degree_Celsius>));
} // namespace