mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-31 19:04:27 +02:00
feat: convertibility of a quantity with a unit one
with the raw value added
Resolves #553
This commit is contained in:
@@ -24,7 +24,7 @@ Here is a small example of operations possible on scalar quantities:
|
|||||||
|
|
||||||
static_assert(2 * m * (3 * m) == 6 * m2);
|
static_assert(2 * m * (3 * m) == 6 * m2);
|
||||||
|
|
||||||
static_assert(10 * km / (5 * km) == 2 * one);
|
static_assert(10 * km / (5 * km) == 2);
|
||||||
|
|
||||||
static_assert(1000 / (1 * s) == 1 * kHz);
|
static_assert(1000 / (1 * s) == 1 * kHz);
|
||||||
```
|
```
|
||||||
@@ -51,7 +51,7 @@ Here is a small example of operations possible on scalar quantities:
|
|||||||
|
|
||||||
static_assert(2 * m * (3 * m) == 6 * m2);
|
static_assert(2 * m * (3 * m) == 6 * m2);
|
||||||
|
|
||||||
static_assert(10 * km / (5 * km) == 2 * one);
|
static_assert(10 * km / (5 * km) == 2);
|
||||||
|
|
||||||
static_assert(1000 / (1 * s) == 1 * kHz);
|
static_assert(1000 / (1 * s) == 1 * kHz);
|
||||||
```
|
```
|
||||||
|
@@ -164,6 +164,21 @@ inline constexpr struct parts_per_million final : named_unit<"ppm", mag_ratio<1,
|
|||||||
inline constexpr auto ppm = parts_per_million;
|
inline constexpr auto ppm = parts_per_million;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Superpowers of the unit `one`
|
||||||
|
|
||||||
|
Quantities of the unit `one` are the only ones that are implicitly convertible from a raw value
|
||||||
|
and explicitly convertible to it. This property also expands to usual arithmetic operators.
|
||||||
|
|
||||||
|
Thanks to the above, we can type:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
quantity<one> inc(quantity<one> q) { return q + 1; }
|
||||||
|
void legacy(double) { /* ... */ }
|
||||||
|
|
||||||
|
if (auto q = inc(42); q != 0)
|
||||||
|
legacy(static_cast<int>(q));
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Angular quantities
|
## Angular quantities
|
||||||
|
|
||||||
|
@@ -64,7 +64,7 @@ int main()
|
|||||||
state next = initial_guess;
|
state next = initial_guess;
|
||||||
for (int index = 1; const auto& measurement : measurements) {
|
for (int index = 1; const auto& measurement : measurements) {
|
||||||
const state& previous = next;
|
const state& previous = next;
|
||||||
const quantity gain = 1. / index * one;
|
const quantity gain = 1. / index;
|
||||||
const state current = state_update(previous, measurement, gain);
|
const state current = state_update(previous, measurement, gain);
|
||||||
next = current;
|
next = current;
|
||||||
print(index++, gain, measurement, current, next);
|
print(index++, gain, measurement, current, next);
|
||||||
|
@@ -177,6 +177,12 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<detail::ValuePreservingTo<Rep> Value>
|
||||||
|
requires(unit == ::mp_units::one)
|
||||||
|
constexpr explicit(false) quantity(Value&& v) : numerical_value_is_an_implementation_detail_(std::forward<Value>(v))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<detail::QuantityConvertibleTo<quantity> Q>
|
template<detail::QuantityConvertibleTo<quantity> Q>
|
||||||
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
|
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
|
||||||
constexpr explicit(!std::convertible_to<typename Q::rep, Rep>) quantity(const Q& q) :
|
constexpr explicit(!std::convertible_to<typename Q::rep, Rep>) quantity(const Q& q) :
|
||||||
@@ -199,6 +205,14 @@ public:
|
|||||||
quantity& operator=(const quantity&) = default;
|
quantity& operator=(const quantity&) = default;
|
||||||
quantity& operator=(quantity&&) = default;
|
quantity& operator=(quantity&&) = default;
|
||||||
|
|
||||||
|
template<detail::ValuePreservingTo<Rep> Value>
|
||||||
|
requires(unit == ::mp_units::one)
|
||||||
|
constexpr quantity& operator=(Value&& v)
|
||||||
|
{
|
||||||
|
numerical_value_is_an_implementation_detail_ = std::forward<Value>(v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
// unit conversions
|
// unit conversions
|
||||||
template<detail::UnitCompatibleWith<unit, quantity_spec> ToU>
|
template<detail::UnitCompatibleWith<unit, quantity_spec> ToU>
|
||||||
requires detail::QuantityConvertibleTo<quantity, quantity<detail::make_reference(quantity_spec, ToU{}), Rep>>
|
requires detail::QuantityConvertibleTo<quantity, quantity<detail::make_reference(quantity_spec, ToU{}), Rep>>
|
||||||
@@ -281,6 +295,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// conversion operators
|
// conversion operators
|
||||||
|
template<typename V_, std::constructible_from<Rep> Value = std::remove_cvref_t<V_>>
|
||||||
|
requires(unit == ::mp_units::one)
|
||||||
|
[[nodiscard]] explicit operator V_() const& noexcept
|
||||||
|
{
|
||||||
|
return numerical_value_is_an_implementation_detail_;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Q_, QuantityLike Q = std::remove_cvref_t<Q_>>
|
template<typename Q_, QuantityLike Q = std::remove_cvref_t<Q_>>
|
||||||
requires detail::QuantityConvertibleTo<quantity, detail::quantity_like_type<Q>>
|
requires detail::QuantityConvertibleTo<quantity, detail::quantity_like_type<Q>>
|
||||||
[[nodiscard]] explicit(is_specialization_of<decltype(quantity_like_traits<Q>::from_numerical_value(
|
[[nodiscard]] explicit(is_specialization_of<decltype(quantity_like_traits<Q>::from_numerical_value(
|
||||||
@@ -480,6 +501,22 @@ public:
|
|||||||
ret::reference};
|
ret::reference};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
|
||||||
|
requires(Q::unit == ::mp_units::one) &&
|
||||||
|
detail::InvokeResultOf<quantity_character::scalar, std::plus<>, Rep, const Value&>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator+(const Q& lhs, const Value& rhs)
|
||||||
|
{
|
||||||
|
return lhs + ::mp_units::quantity{rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
|
||||||
|
requires(Q::unit == ::mp_units::one) &&
|
||||||
|
detail::InvokeResultOf<quantity_character::scalar, std::plus<>, Rep, const Value&>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator+(const Value& lhs, const Q& rhs)
|
||||||
|
{
|
||||||
|
return ::mp_units::quantity{lhs} + rhs;
|
||||||
|
}
|
||||||
|
|
||||||
template<std::derived_from<quantity> Q, auto R2, typename Rep2>
|
template<std::derived_from<quantity> Q, auto R2, typename Rep2>
|
||||||
requires detail::CommonlyInvocableQuantities<std::minus<>, quantity, quantity<R2, Rep2>>
|
requires detail::CommonlyInvocableQuantities<std::minus<>, quantity, quantity<R2, Rep2>>
|
||||||
[[nodiscard]] friend constexpr Quantity auto operator-(const Q& lhs, const quantity<R2, Rep2>& rhs)
|
[[nodiscard]] friend constexpr Quantity auto operator-(const Q& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
@@ -491,6 +528,22 @@ public:
|
|||||||
ret::reference};
|
ret::reference};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
|
||||||
|
requires(Q::unit == ::mp_units::one) &&
|
||||||
|
detail::InvokeResultOf<quantity_character::scalar, std::minus<>, Rep, const Value&>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator-(const Q& lhs, const Value& rhs)
|
||||||
|
{
|
||||||
|
return lhs - ::mp_units::quantity{rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
|
||||||
|
requires(Q::unit == ::mp_units::one) &&
|
||||||
|
detail::InvokeResultOf<quantity_character::scalar, std::minus<>, Rep, const Value&>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator-(const Value& lhs, const Q& rhs)
|
||||||
|
{
|
||||||
|
return ::mp_units::quantity{lhs} - rhs;
|
||||||
|
}
|
||||||
|
|
||||||
template<std::derived_from<quantity> Q, auto R2, typename Rep2>
|
template<std::derived_from<quantity> Q, auto R2, typename Rep2>
|
||||||
requires(!treat_as_floating_point<Rep>) && (!treat_as_floating_point<Rep2>) &&
|
requires(!treat_as_floating_point<Rep>) && (!treat_as_floating_point<Rep2>) &&
|
||||||
detail::CommonlyInvocableQuantities<std::modulus<>, quantity, quantity<R2, Rep2>>
|
detail::CommonlyInvocableQuantities<std::modulus<>, quantity, quantity<R2, Rep2>>
|
||||||
@@ -504,6 +557,22 @@ public:
|
|||||||
ret::reference};
|
ret::reference};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
|
||||||
|
requires(Q::unit == ::mp_units::one) &&
|
||||||
|
detail::InvokeResultOf<quantity_character::scalar, std::modulus<>, Rep, const Value&>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator%(const Q& lhs, const Value& rhs)
|
||||||
|
{
|
||||||
|
return lhs % ::mp_units::quantity{rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
|
||||||
|
requires(Q::unit == ::mp_units::one) &&
|
||||||
|
detail::InvokeResultOf<quantity_character::scalar, std::modulus<>, Rep, const Value&>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator%(const Value& lhs, const Q& rhs)
|
||||||
|
{
|
||||||
|
return ::mp_units::quantity{lhs} % rhs;
|
||||||
|
}
|
||||||
|
|
||||||
template<std::derived_from<quantity> Q, auto R2, typename Rep2>
|
template<std::derived_from<quantity> Q, auto R2, typename Rep2>
|
||||||
requires detail::InvocableQuantities<std::multiplies<>, quantity, quantity<R2, Rep2>>
|
requires detail::InvocableQuantities<std::multiplies<>, quantity, quantity<R2, Rep2>>
|
||||||
[[nodiscard]] friend constexpr Quantity auto operator*(const Q& lhs, const quantity<R2, Rep2>& rhs)
|
[[nodiscard]] friend constexpr Quantity auto operator*(const Q& lhs, const quantity<R2, Rep2>& rhs)
|
||||||
@@ -563,6 +632,13 @@ public:
|
|||||||
return ct_lhs.numerical_value_ref_in(ct::unit) == ct_rhs.numerical_value_ref_in(ct::unit);
|
return ct_lhs.numerical_value_ref_in(ct::unit) == ct_rhs.numerical_value_ref_in(ct::unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
|
||||||
|
requires(Q::unit == ::mp_units::one) && std::equality_comparable_with<Rep, Value>
|
||||||
|
[[nodiscard]] friend constexpr bool operator==(const Q& lhs, const Value& rhs)
|
||||||
|
{
|
||||||
|
return lhs.numerical_value_ref_in(unit) == rhs;
|
||||||
|
}
|
||||||
|
|
||||||
template<std::derived_from<quantity> Q, auto R2, typename Rep2>
|
template<std::derived_from<quantity> Q, auto R2, typename Rep2>
|
||||||
requires requires { typename std::common_type_t<quantity, quantity<R2, Rep2>>; } &&
|
requires requires { typename std::common_type_t<quantity, quantity<R2, Rep2>>; } &&
|
||||||
std::three_way_comparable<typename std::common_type_t<quantity, quantity<R2, Rep2>>::rep>
|
std::three_way_comparable<typename std::common_type_t<quantity, quantity<R2, Rep2>>::rep>
|
||||||
@@ -573,6 +649,13 @@ public:
|
|||||||
const ct ct_rhs(rhs);
|
const ct ct_rhs(rhs);
|
||||||
return ct_lhs.numerical_value_ref_in(ct::unit) <=> ct_rhs.numerical_value_ref_in(ct::unit);
|
return ct_lhs.numerical_value_ref_in(ct::unit) <=> ct_rhs.numerical_value_ref_in(ct::unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::derived_from<quantity> Q, RepresentationOf<quantity_character::scalar> Value>
|
||||||
|
requires(Q::unit == ::mp_units::one) && std::three_way_comparable_with<Rep, Value>
|
||||||
|
[[nodiscard]] friend constexpr auto operator<=>(const Q& lhs, const Value& rhs)
|
||||||
|
{
|
||||||
|
return lhs.numerical_value_ref_in(unit) <=> rhs;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// CTAD
|
// CTAD
|
||||||
@@ -599,7 +682,16 @@ template<mp_units::Quantity Q1, mp_units::Quantity Q2>
|
|||||||
typename std::common_type_t<typename Q1::rep, typename Q2::rep>;
|
typename std::common_type_t<typename Q1::rep, typename Q2::rep>;
|
||||||
}
|
}
|
||||||
struct std::common_type<Q1, Q2> {
|
struct std::common_type<Q1, Q2> {
|
||||||
public:
|
|
||||||
using type = mp_units::quantity<mp_units::common_reference(Q1::reference, Q2::reference),
|
using type = mp_units::quantity<mp_units::common_reference(Q1::reference, Q2::reference),
|
||||||
std::common_type_t<typename Q1::rep, typename Q2::rep>>;
|
std::common_type_t<typename Q1::rep, typename Q2::rep>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<mp_units::Quantity Q, mp_units::RepresentationOf<mp_units::quantity_character::scalar> Value>
|
||||||
|
requires(Q::unit == mp_units::one) && requires { typename std::common_type_t<typename Q::rep, Value>; }
|
||||||
|
struct std::common_type<Q, Value> {
|
||||||
|
using type = mp_units::quantity<Q::reference, std::common_type_t<typename Q::rep, Value>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<mp_units::Quantity Q, mp_units::RepresentationOf<mp_units::quantity_character::scalar> Value>
|
||||||
|
requires(Q::unit == mp_units::one) && requires { typename std::common_type_t<typename Q::rep, Value>; }
|
||||||
|
struct std::common_type<Value, Q> : std::common_type<Q, Value> {};
|
||||||
|
@@ -126,9 +126,9 @@ static_assert(quantity<isq::length[m], double>::min().numerical_value_in(m) == s
|
|||||||
static_assert(quantity<isq::length[m], double>::max().numerical_value_in(m) == std::numeric_limits<double>::max());
|
static_assert(quantity<isq::length[m], double>::max().numerical_value_in(m) == std::numeric_limits<double>::max());
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
// construction from a value
|
// no construction from value (unless unit one)
|
||||||
//////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
|
|
||||||
// construction from a value is private
|
// construction from a value is private
|
||||||
static_assert(!std::constructible_from<quantity<isq::length[m]>, double>);
|
static_assert(!std::constructible_from<quantity<isq::length[m]>, double>);
|
||||||
@@ -137,11 +137,17 @@ static_assert(!std::convertible_to<double, quantity<isq::length[m]>>);
|
|||||||
static_assert(!std::constructible_from<quantity<isq::length[m], int>, int>);
|
static_assert(!std::constructible_from<quantity<isq::length[m], int>, int>);
|
||||||
static_assert(!std::convertible_to<int, quantity<isq::length[m], int>>);
|
static_assert(!std::convertible_to<int, quantity<isq::length[m], int>>);
|
||||||
|
|
||||||
static_assert(!std::constructible_from<quantity<dimensionless[one]>, double>);
|
static_assert(std::constructible_from<quantity<one>, double>);
|
||||||
static_assert(!std::convertible_to<double, quantity<dimensionless[one]>>);
|
static_assert(std::convertible_to<double, quantity<one>>);
|
||||||
|
|
||||||
static_assert(!std::constructible_from<quantity<dimensionless[one]>, int>);
|
static_assert(std::constructible_from<quantity<one>, int>);
|
||||||
static_assert(!std::convertible_to<int, quantity<dimensionless[one]>>);
|
static_assert(std::convertible_to<int, quantity<one>>);
|
||||||
|
|
||||||
|
static_assert(std::constructible_from<quantity<dimensionless[one]>, double>);
|
||||||
|
static_assert(std::convertible_to<double, quantity<dimensionless[one]>>);
|
||||||
|
|
||||||
|
static_assert(std::constructible_from<quantity<dimensionless[one]>, int>);
|
||||||
|
static_assert(std::convertible_to<int, quantity<dimensionless[one]>>);
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
@@ -200,6 +206,24 @@ static_assert(quantity<isq::length[km], int>(2 * km).numerical_value_in(km) == 2
|
|||||||
static_assert(quantity<isq::length[km]>(1500 * m).numerical_value_in(km) == 1.5);
|
static_assert(quantity<isq::length[km]>(1500 * m).numerical_value_in(km) == 1.5);
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
// explicit conversion to a number (when unit is one)
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static_assert(!std::convertible_to<quantity<one>, double>);
|
||||||
|
static_assert(std::constructible_from<double, quantity<one>>);
|
||||||
|
static_assert(!std::convertible_to<quantity<isq::angular_measure[one]>, double>);
|
||||||
|
static_assert(std::constructible_from<double, quantity<isq::angular_measure[one]>>);
|
||||||
|
static_assert(!std::convertible_to<quantity<one>, int>);
|
||||||
|
static_assert(std::constructible_from<int, quantity<one>>);
|
||||||
|
static_assert(!std::convertible_to<quantity<isq::angular_measure[one]>, int>);
|
||||||
|
static_assert(std::constructible_from<int, quantity<isq::angular_measure[one]>>);
|
||||||
|
static_assert(!std::convertible_to<quantity<one, int>, double>);
|
||||||
|
static_assert(std::constructible_from<double, quantity<one, int>>);
|
||||||
|
static_assert(!std::convertible_to<quantity<isq::angular_measure[one], int>, double>);
|
||||||
|
static_assert(std::constructible_from<double, quantity<isq::angular_measure[one], int>>);
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
// converting to a different unit
|
// converting to a different unit
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
@@ -320,6 +344,10 @@ static_assert(quantity{123. * m}.unit == si::metre);
|
|||||||
static_assert(quantity{123. * m}.quantity_spec == kind_of<isq::length>);
|
static_assert(quantity{123. * m}.quantity_spec == kind_of<isq::length>);
|
||||||
static_assert(quantity{123. * h}.unit == si::hour);
|
static_assert(quantity{123. * h}.unit == si::hour);
|
||||||
static_assert(quantity{123. * h}.quantity_spec == kind_of<isq::time>);
|
static_assert(quantity{123. * h}.quantity_spec == kind_of<isq::time>);
|
||||||
|
static_assert(std::is_same_v<decltype(quantity{123})::rep, int>);
|
||||||
|
static_assert(std::is_same_v<decltype(quantity{123.})::rep, double>);
|
||||||
|
static_assert(quantity{123}.unit == one);
|
||||||
|
static_assert(quantity{123}.quantity_spec == kind_of<dimensionless>);
|
||||||
|
|
||||||
#if MP_UNITS_HOSTED
|
#if MP_UNITS_HOSTED
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
@@ -350,6 +378,11 @@ static_assert([]() {
|
|||||||
}()
|
}()
|
||||||
.numerical_value_in(m) == 1);
|
.numerical_value_in(m) == 1);
|
||||||
|
|
||||||
|
static_assert([]() {
|
||||||
|
quantity q(1);
|
||||||
|
return q = 2;
|
||||||
|
}()
|
||||||
|
.numerical_value_in(one) == 2);
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
// unary operators
|
// unary operators
|
||||||
@@ -752,6 +785,17 @@ static_assert(4 / (2 * one) == 2 * one);
|
|||||||
static_assert(4 * one / 2 == 2 * one);
|
static_assert(4 * one / 2 == 2 * one);
|
||||||
static_assert(4 * one % (2 * one) == 0 * one);
|
static_assert(4 * one % (2 * one) == 0 * one);
|
||||||
|
|
||||||
|
static_assert(1 * one + 1 == 2);
|
||||||
|
static_assert(1 + 1 * one == 2);
|
||||||
|
static_assert(2 * one - 1 == 1);
|
||||||
|
static_assert(2 - 1 * one == 1);
|
||||||
|
static_assert(1 * one + 1.23 == 2.23);
|
||||||
|
static_assert(1 + 1.23 * one == 2.23);
|
||||||
|
static_assert(2.23 * one - 1 == 1.23);
|
||||||
|
static_assert(2.23 - 1 * one == 1.23);
|
||||||
|
static_assert(4 * one % (2) == 0);
|
||||||
|
static_assert(4 % (2 * one) == 0);
|
||||||
|
|
||||||
static_assert(2 * rad * (2 * rad) == 4 * pow<2>(rad));
|
static_assert(2 * rad * (2 * rad) == 4 * pow<2>(rad));
|
||||||
|
|
||||||
// modulo arithmetics
|
// modulo arithmetics
|
||||||
@@ -912,6 +956,9 @@ static_assert(!(123 * km > 321'000 * m));
|
|||||||
static_assert(!(123 * km > 123'000 * m));
|
static_assert(!(123 * km > 123'000 * m));
|
||||||
static_assert(!(123 * km >= 321'000 * m));
|
static_assert(!(123 * km >= 321'000 * m));
|
||||||
|
|
||||||
|
static_assert(1 * one < 2);
|
||||||
|
static_assert(1 < 2 * one);
|
||||||
|
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// dimensionless
|
// dimensionless
|
||||||
@@ -925,6 +972,32 @@ static_assert(50. * m / (100. * m) == 50 * percent);
|
|||||||
static_assert((50. * percent).numerical_value_in(one) == 0.5);
|
static_assert((50. * percent).numerical_value_in(one) == 0.5);
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// common_type
|
||||||
|
//////////////////
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
is_same_v<std::common_type_t<quantity<isq::speed[m / s], int>, quantity<(isq::length / isq::time)[m / s], double>>,
|
||||||
|
quantity<isq::speed[m / s], double>>);
|
||||||
|
static_assert(is_same_v<std::common_type_t<quantity<(isq::mass * pow<2>(isq::length / isq::time))[J], double>,
|
||||||
|
quantity<isq::energy[kg * m2 / s2], double>>,
|
||||||
|
quantity<isq::energy[J], double>>);
|
||||||
|
|
||||||
|
#if MP_UNITS_HOSTED
|
||||||
|
static_assert(is_same_v<std::common_type_t<quantity<si::second, int>, std::chrono::seconds>, std::chrono::seconds>);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static_assert(is_same_v<std::common_type_t<quantity<one, int>, int>, quantity<one, int>>);
|
||||||
|
// static_assert(is_same_v<std::common_type_t<quantity<one, int>, double>, quantity<one, double>>);
|
||||||
|
// static_assert(is_same_v<std::common_type_t<quantity<one, double>, int>, quantity<one, double>>);
|
||||||
|
static_assert(is_same_v<std::common_type_t<quantity<isq::angular_measure[one], int>, int>,
|
||||||
|
quantity<isq::angular_measure[one], int>>);
|
||||||
|
// static_assert(is_same_v<std::common_type_t<quantity<isq::angular_measure[one], int>, double>,
|
||||||
|
// quantity<isq::angular_measure[one], double>>);
|
||||||
|
// static_assert(is_same_v<std::common_type_t<quantity<isq::angular_measure[one], double>, int>,
|
||||||
|
// quantity<isq::angular_measure[one], double>>);
|
||||||
|
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// value_cast
|
// value_cast
|
||||||
//////////////////
|
//////////////////
|
||||||
|
Reference in New Issue
Block a user