refactor: unit-related constexpr functions compile-time evaluation limited to only one that determines the return type
This commit is contained in:
1 parent
fb77585593
commit
760d48502d
5 files changed
+79
-123
No files matched your search
@@ -64,10 +64,11 @@ template<Quantity To, typename From>
|
||||
// warnings on conversions
|
||||
} else {
|
||||
// scale the number
|
||||
constexpr Magnitude auto c_mag = get_canonical_unit(q_unit).mag / get_canonical_unit(To::unit).mag;
|
||||
constexpr Magnitude auto num = numerator(c_mag);
|
||||
constexpr Magnitude auto den = denominator(c_mag);
|
||||
constexpr Magnitude auto irr = c_mag * (den / num);
|
||||
constexpr Magnitude auto c_mag =
|
||||
decltype(decltype(get_canonical_unit(q_unit))::mag / decltype(get_canonical_unit(To::unit))::mag){};
|
||||
constexpr Magnitude auto num = decltype(numerator(c_mag)){};
|
||||
constexpr Magnitude auto den = decltype(denominator(c_mag)){};
|
||||
constexpr Magnitude auto irr = decltype(c_mag * decltype(den / num){}){};
|
||||
using c_rep_type = maybe_common_type<typename std::remove_reference_t<From>::rep, typename To::rep>;
|
||||
using c_mag_type = common_magnitude_type<c_mag>;
|
||||
using multiplier_type = conditional<
|
||||
|
||||
@@ -46,8 +46,9 @@ namespace mp_units {
|
||||
namespace detail {
|
||||
|
||||
template<auto UFrom, auto UTo>
|
||||
concept IntegralConversionFactor = Unit<decltype(UFrom)> && Unit<decltype(UTo)> &&
|
||||
is_integral(get_canonical_unit(UFrom).mag / get_canonical_unit(UTo).mag);
|
||||
concept IntegralConversionFactor =
|
||||
Unit<decltype(UFrom)> && Unit<decltype(UTo)> &&
|
||||
is_integral(decltype(decltype(get_canonical_unit(UFrom))::mag / decltype(get_canonical_unit(UTo))::mag){});
|
||||
|
||||
template<typename QFrom, typename QTo>
|
||||
concept QuantityConvertibleTo =
|
||||
|
||||
@@ -321,22 +321,12 @@ struct is_one<struct one> : std::true_type {};
|
||||
* @tparam U a unit to use as a `reference_unit`
|
||||
* @tparam M a Magnitude representing an absolute scaling factor of this unit
|
||||
*/
|
||||
template<Magnitude M, Unit U>
|
||||
template<Magnitude auto M, Unit auto U>
|
||||
struct canonical_unit {
|
||||
M mag;
|
||||
U reference_unit;
|
||||
static constexpr auto mag = M;
|
||||
static constexpr auto reference_unit = U;
|
||||
};
|
||||
|
||||
#if MP_UNITS_COMP_CLANG
|
||||
|
||||
template<Magnitude M, Unit U>
|
||||
canonical_unit(M, U) -> canonical_unit<M, U>;
|
||||
|
||||
#endif
|
||||
|
||||
template<Unit T, symbol_text Symbol, detail::QuantityKindSpec auto Q, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Q, Args...>&);
|
||||
|
||||
template<Unit T, symbol_text Symbol, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Args...>&);
|
||||
|
||||
@@ -352,64 +342,61 @@ template<Unit T, typename... Expr>
|
||||
template<Unit T, auto M, typename U>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const scaled_unit<M, U>&)
|
||||
{
|
||||
auto base = get_canonical_unit_impl(U{}, U{});
|
||||
return canonical_unit{M * base.mag, base.reference_unit};
|
||||
}
|
||||
|
||||
template<Unit T, symbol_text Symbol, detail::QuantityKindSpec auto Q, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Q, Args...>&)
|
||||
{
|
||||
return canonical_unit{mag<1>, t};
|
||||
using base = decltype(get_canonical_unit_impl(U{}, U{}));
|
||||
return canonical_unit<decltype(M * base::mag){}, base::reference_unit>{};
|
||||
}
|
||||
|
||||
template<Unit T, symbol_text Symbol, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit<Symbol, Args...>&)
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const named_unit<Symbol, Args...>&)
|
||||
{
|
||||
return canonical_unit{mag<1>, t};
|
||||
return canonical_unit<mag<1>, T{}>{};
|
||||
}
|
||||
|
||||
template<Unit T, symbol_text Symbol, Unit auto U, auto... Args>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const named_unit<Symbol, U, Args...>&)
|
||||
{
|
||||
return get_canonical_unit_impl(U, U);
|
||||
return decltype(get_canonical_unit_impl(U, U)){};
|
||||
}
|
||||
|
||||
template<typename F, int Num, int... Den, typename... Us>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(const power<F, Num, Den...>&, const type_list<Us...>&)
|
||||
{
|
||||
auto mag = (mp_units::mag<1> * ... * pow<Num, Den...>(get_canonical_unit_impl(Us{}, Us{}).mag));
|
||||
auto u = (one * ... * pow<Num, Den...>(get_canonical_unit_impl(Us{}, Us{}).reference_unit));
|
||||
return canonical_unit{mag, u};
|
||||
using mag = decltype((mp_units::mag<1> * ... * pow<Num, Den...>(decltype(get_canonical_unit_impl(Us{}, Us{}))::mag)));
|
||||
using u = decltype((one * ... * pow<Num, Den...>(decltype(get_canonical_unit_impl(Us{}, Us{}))::reference_unit)));
|
||||
return canonical_unit<mag{}, u{}>{};
|
||||
}
|
||||
|
||||
template<typename T, typename F, int Num, int... Den>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const power<F, Num, Den...>&)
|
||||
{
|
||||
auto base = get_canonical_unit_impl(F{}, F{});
|
||||
if constexpr (requires { typename decltype(base.reference_unit)::_num_; }) {
|
||||
auto num = get_canonical_unit_impl(power<F, Num, Den...>{}, typename decltype(base.reference_unit)::_num_{});
|
||||
auto den = get_canonical_unit_impl(power<F, Num, Den...>{}, typename decltype(base.reference_unit)::_den_{});
|
||||
return canonical_unit{pow<Num, Den...>(base.mag) * num.mag / den.mag, num.reference_unit / den.reference_unit};
|
||||
using base = decltype(get_canonical_unit_impl(F{}, F{}));
|
||||
if constexpr (requires { typename decltype(base::reference_unit)::_num_; }) {
|
||||
using num =
|
||||
decltype(get_canonical_unit_impl(power<F, Num, Den...>{}, typename decltype(base::reference_unit)::_num_{}));
|
||||
using den =
|
||||
decltype(get_canonical_unit_impl(power<F, Num, Den...>{}, typename decltype(base::reference_unit)::_den_{}));
|
||||
return canonical_unit<decltype(decltype(pow<Num, Den...>(base::mag) * num::mag){} / den::mag){},
|
||||
decltype(num::reference_unit / den::reference_unit){}>{};
|
||||
} else {
|
||||
return canonical_unit{pow<Num, Den...>(base.mag),
|
||||
derived_unit<power<decltype(base.reference_unit), Num, Den...>>{}};
|
||||
return canonical_unit<decltype(pow<Num, Den...>(base::mag)){},
|
||||
derived_unit<power<std::remove_const_t<decltype(base::reference_unit)>, Num, Den...>>{}>{};
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Us>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(const type_list<Us...>&)
|
||||
{
|
||||
auto m = (mp_units::mag<1> * ... * get_canonical_unit_impl(Us{}, Us{}).mag);
|
||||
auto u = (one * ... * get_canonical_unit_impl(Us{}, Us{}).reference_unit);
|
||||
return canonical_unit{m, u};
|
||||
using m = decltype((mp_units::mag<1> * ... * decltype(get_canonical_unit_impl(Us{}, Us{}))::mag));
|
||||
using u = decltype((one * ... * decltype(get_canonical_unit_impl(Us{}, Us{}))::reference_unit));
|
||||
return canonical_unit<m{}, u{}>{};
|
||||
}
|
||||
|
||||
template<Unit T, typename... Expr>
|
||||
[[nodiscard]] consteval auto get_canonical_unit_impl(T, const derived_unit<Expr...>&)
|
||||
{
|
||||
auto num = get_canonical_unit_impl(typename derived_unit<Expr...>::_num_{});
|
||||
auto den = get_canonical_unit_impl(typename derived_unit<Expr...>::_den_{});
|
||||
return canonical_unit{num.mag / den.mag, num.reference_unit / den.reference_unit};
|
||||
using num = decltype(get_canonical_unit_impl(typename derived_unit<Expr...>::_num_{}));
|
||||
using den = decltype(get_canonical_unit_impl(typename derived_unit<Expr...>::_den_{}));
|
||||
return canonical_unit<decltype(num::mag / den::mag){}, decltype(num::reference_unit / den::reference_unit){}>{};
|
||||
}
|
||||
|
||||
template<Unit Lhs, Unit Rhs>
|
||||
@@ -422,7 +409,10 @@ using type_list_of_unit_less = expr_less<T1, T2, unit_less>;
|
||||
|
||||
// TODO this should really be in the `details` namespace but is used in `chrono.h` (a part of mp_units.systems)
|
||||
// Even though it is not exported, it is visible to the other module via ADL
|
||||
[[nodiscard]] consteval auto get_canonical_unit(Unit auto u) { return detail::get_canonical_unit_impl(u, u); }
|
||||
[[nodiscard]] consteval auto get_canonical_unit(Unit auto u)
|
||||
{
|
||||
return decltype(detail::get_canonical_unit_impl(u, u)){};
|
||||
}
|
||||
|
||||
MP_UNITS_EXPORT_BEGIN
|
||||
|
||||
@@ -448,7 +438,7 @@ template<Magnitude M, Unit U>
|
||||
template<Magnitude M, Unit U>
|
||||
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator/(M mag, U u)
|
||||
{
|
||||
return mag * inverse(u);
|
||||
return decltype(mag * inverse(u)){};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -460,13 +450,13 @@ template<Unit Lhs, Unit Rhs>
|
||||
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator*(Lhs lhs, Rhs rhs)
|
||||
{
|
||||
if constexpr (detail::is_specialization_of_scaled_unit<Lhs> && detail::is_specialization_of_scaled_unit<Rhs>)
|
||||
return (Lhs::mag * Rhs::mag) * (Lhs::reference_unit * Rhs::reference_unit);
|
||||
return decltype(Lhs::mag * Rhs::mag){} * decltype(Lhs::reference_unit * Rhs::reference_unit){};
|
||||
else if constexpr (detail::is_specialization_of_scaled_unit<Lhs>)
|
||||
return Lhs::mag * (Lhs::reference_unit * rhs);
|
||||
return decltype(Lhs::mag * decltype(Lhs::reference_unit * rhs){}){};
|
||||
else if constexpr (detail::is_specialization_of_scaled_unit<Rhs>)
|
||||
return Rhs::mag * (lhs * Rhs::reference_unit);
|
||||
return decltype(Rhs::mag * decltype(lhs * Rhs::reference_unit){}){};
|
||||
else
|
||||
return detail::expr_multiply<derived_unit, struct one, detail::type_list_of_unit_less>(lhs, rhs);
|
||||
return decltype(detail::expr_multiply<derived_unit, struct one, detail::type_list_of_unit_less>(lhs, rhs)){};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,69 +468,36 @@ template<Unit Lhs, Unit Rhs>
|
||||
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator/(Lhs lhs, Rhs rhs)
|
||||
{
|
||||
if constexpr (detail::is_specialization_of_scaled_unit<Lhs> && detail::is_specialization_of_scaled_unit<Rhs>)
|
||||
return (Lhs::mag / Rhs::mag) * (Lhs::reference_unit / Rhs::reference_unit);
|
||||
return decltype(Lhs::mag / Rhs::mag){} * decltype(Lhs::reference_unit / Rhs::reference_unit){};
|
||||
else if constexpr (detail::is_specialization_of_scaled_unit<Lhs>)
|
||||
return Lhs::mag * (Lhs::reference_unit / rhs);
|
||||
return Lhs::mag * decltype(Lhs::reference_unit / rhs){};
|
||||
else if constexpr (detail::is_specialization_of_scaled_unit<Rhs>)
|
||||
return mag<1> / Rhs::mag * (lhs / Rhs::reference_unit);
|
||||
return decltype(mag<1> / Rhs::mag){} * decltype(lhs / Rhs::reference_unit){};
|
||||
else
|
||||
return detail::expr_divide<derived_unit, struct one, detail::type_list_of_unit_less>(lhs, rhs);
|
||||
}
|
||||
|
||||
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto inverse(Unit auto u) { return one / u; }
|
||||
[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto inverse(Unit auto u) { return decltype(one / u){}; }
|
||||
|
||||
MP_UNITS_EXPORT_END
|
||||
|
||||
namespace detail {
|
||||
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(...) { return false; }
|
||||
|
||||
template<symbol_text Symbol, auto... D>
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const named_unit<Symbol, D...>&,
|
||||
const named_unit<Symbol, D...>&)
|
||||
[[nodiscard]] consteval auto have_same_canonical_reference_unit(Unit auto u1, Unit auto u2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename F1, typename F2, auto... Vs>
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const power<F1, Vs...>&, const power<F2, Vs...>&)
|
||||
{
|
||||
return have_same_canonical_reference_unit_impl(F1{}, F2{});
|
||||
}
|
||||
|
||||
template<typename... Us1, typename... Us2>
|
||||
requires(sizeof...(Us1) == sizeof...(Us2))
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const type_list<Us1...>&, const type_list<Us2...>&)
|
||||
{
|
||||
return (... && have_same_canonical_reference_unit_impl(Us1{}, Us2{}));
|
||||
}
|
||||
|
||||
template<typename... Expr1, typename... Expr2>
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const derived_unit<Expr1...>&,
|
||||
const derived_unit<Expr2...>&)
|
||||
{
|
||||
return have_same_canonical_reference_unit_impl(typename derived_unit<Expr1...>::_num_{},
|
||||
typename derived_unit<Expr2...>::_num_{}) &&
|
||||
have_same_canonical_reference_unit_impl(typename derived_unit<Expr1...>::_den_{},
|
||||
typename derived_unit<Expr2...>::_den_{});
|
||||
}
|
||||
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit(Unit auto u1, Unit auto u2)
|
||||
{
|
||||
auto canonical_lhs = get_canonical_unit(u1);
|
||||
auto canonical_rhs = get_canonical_unit(u2);
|
||||
return have_same_canonical_reference_unit_impl(canonical_lhs.reference_unit, canonical_rhs.reference_unit);
|
||||
using canonical_lhs = decltype(get_canonical_unit(u1));
|
||||
using canonical_rhs = decltype(get_canonical_unit(u2));
|
||||
return std::is_same<decltype(canonical_lhs::reference_unit), decltype(canonical_rhs::reference_unit)>{};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
MP_UNITS_EXPORT [[nodiscard]] consteval bool operator==(Unit auto lhs, Unit auto rhs)
|
||||
MP_UNITS_EXPORT template<Unit U1, Unit U2>
|
||||
[[nodiscard]] consteval bool operator==(U1 lhs, U2 rhs)
|
||||
{
|
||||
auto canonical_lhs = get_canonical_unit(lhs);
|
||||
auto canonical_rhs = get_canonical_unit(rhs);
|
||||
return detail::have_same_canonical_reference_unit(canonical_lhs.reference_unit, canonical_rhs.reference_unit) &&
|
||||
canonical_lhs.mag == canonical_rhs.mag;
|
||||
return decltype(detail::have_same_canonical_reference_unit(lhs, rhs))::value &&
|
||||
decltype(get_canonical_unit(lhs))::mag == decltype(get_canonical_unit(rhs))::mag;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@@ -575,7 +532,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
|
||||
else if constexpr (detail::is_specialization_of_scaled_unit<U>)
|
||||
return scaled_unit<pow<Num, Den>(U::mag), decltype(pow<Num, Den>(U::reference_unit))>{};
|
||||
else if constexpr (detail::is_specialization_of_derived_unit<U>)
|
||||
return detail::expr_pow<Num, Den, derived_unit, struct one, detail::type_list_of_unit_less>(u);
|
||||
return decltype(detail::expr_pow<Num, Den, derived_unit, struct one, detail::type_list_of_unit_less>(u)){};
|
||||
else if constexpr (Den == 1)
|
||||
return derived_unit<power<U, Num>>{};
|
||||
else
|
||||
@@ -589,7 +546,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
|
||||
*
|
||||
* @return Unit The result of computation
|
||||
*/
|
||||
[[nodiscard]] consteval Unit auto sqrt(Unit auto u) { return pow<1, 2>(u); }
|
||||
[[nodiscard]] consteval Unit auto sqrt(Unit auto u) { return decltype(pow<1, 2>(u)){}; }
|
||||
|
||||
/**
|
||||
* @brief Computes the cubic root of a unit
|
||||
@@ -598,7 +555,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
|
||||
*
|
||||
* @return Unit The result of computation
|
||||
*/
|
||||
[[nodiscard]] consteval Unit auto cbrt(Unit auto u) { return pow<1, 3>(u); }
|
||||
[[nodiscard]] consteval Unit auto cbrt(Unit auto u) { return decltype(pow<1, 3>(u)){}; }
|
||||
|
||||
/**
|
||||
* @brief Computes the square power of a unit
|
||||
@@ -607,7 +564,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
|
||||
*
|
||||
* @return Unit The result of computation
|
||||
*/
|
||||
[[nodiscard]] consteval Unit auto square(Unit auto u) { return pow<2>(u); }
|
||||
[[nodiscard]] consteval Unit auto square(Unit auto u) { return decltype(pow<2>(u)){}; }
|
||||
|
||||
/**
|
||||
* @brief Computes the cubic power of a unit
|
||||
@@ -616,7 +573,7 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Unit U>
|
||||
*
|
||||
* @return Unit The result of computation
|
||||
*/
|
||||
[[nodiscard]] consteval Unit auto cubic(Unit auto u) { return pow<3>(u); }
|
||||
[[nodiscard]] consteval Unit auto cubic(Unit auto u) { return decltype(pow<3>(u)){}; }
|
||||
|
||||
|
||||
// common dimensionless units
|
||||
@@ -631,7 +588,7 @@ inline constexpr auto ppm = parts_per_million;
|
||||
// convertible_to
|
||||
[[nodiscard]] consteval bool convertible(Unit auto from, Unit auto to)
|
||||
{
|
||||
return detail::have_same_canonical_reference_unit(from, to);
|
||||
return decltype(detail::have_same_canonical_reference_unit(from, to))::value;
|
||||
}
|
||||
|
||||
// Common unit
|
||||
@@ -639,7 +596,7 @@ inline constexpr auto ppm = parts_per_million;
|
||||
|
||||
template<Unit U1, Unit U2>
|
||||
[[nodiscard]] consteval Unit auto common_unit(U1 u1, U2 u2)
|
||||
requires(detail::have_same_canonical_reference_unit(u1, u2))
|
||||
requires(decltype(detail::have_same_canonical_reference_unit(u1, u2))::value)
|
||||
{
|
||||
if constexpr (U1{} == U2{}) {
|
||||
if constexpr (std::derived_from<U1, U2>)
|
||||
@@ -648,18 +605,18 @@ template<Unit U1, Unit U2>
|
||||
return u2;
|
||||
else
|
||||
// TODO Check if there is a better choice here
|
||||
return detail::better_type_name(u1, u2);
|
||||
return decltype(detail::better_type_name(u1, u2)){};
|
||||
} else {
|
||||
constexpr auto canonical_lhs = get_canonical_unit(U1{});
|
||||
constexpr auto canonical_rhs = get_canonical_unit(U2{});
|
||||
using canonical_lhs = decltype(get_canonical_unit(U1{}));
|
||||
using canonical_rhs = decltype(get_canonical_unit(U2{}));
|
||||
|
||||
if constexpr (is_integral(canonical_lhs.mag / canonical_rhs.mag))
|
||||
if constexpr (is_integral(decltype(canonical_lhs::mag / canonical_rhs::mag){}))
|
||||
return u2;
|
||||
else if constexpr (is_integral(canonical_rhs.mag / canonical_lhs.mag))
|
||||
else if constexpr (is_integral(decltype(canonical_rhs::mag / canonical_lhs::mag){}))
|
||||
return u1;
|
||||
else {
|
||||
constexpr auto cm = detail::common_magnitude(canonical_lhs.mag, canonical_rhs.mag);
|
||||
return scaled_unit<cm, decltype(canonical_lhs.reference_unit)>{};
|
||||
constexpr auto cm = decltype(detail::common_magnitude(canonical_lhs::mag, canonical_rhs::mag)){};
|
||||
return scaled_unit<cm, std::remove_const_t<decltype(canonical_lhs::reference_unit)>>{};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -667,7 +624,7 @@ template<Unit U1, Unit U2>
|
||||
[[nodiscard]] consteval Unit auto common_unit(Unit auto u1, Unit auto u2, Unit auto u3, Unit auto... rest)
|
||||
requires requires { common_unit(common_unit(u1, u2), u3, rest...); }
|
||||
{
|
||||
return common_unit(common_unit(u1, u2), u3, rest...);
|
||||
return decltype(common_unit(common_unit(u1, u2), u3, rest...)){};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,9 +33,8 @@ namespace mp_units {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// do not refactor below to a variable template - GCC-11 does not like it
|
||||
template<typename T>
|
||||
struct is_unit : std::false_type {};
|
||||
inline constexpr bool is_unit = false;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -45,7 +44,7 @@ struct is_unit : std::false_type {};
|
||||
* Satisfied by all unit types provided by the library.
|
||||
*/
|
||||
MP_UNITS_EXPORT template<typename T>
|
||||
concept Unit = detail::is_unit<T>::value;
|
||||
concept Unit = detail::is_unit<T>;
|
||||
|
||||
template<Magnitude auto M, Unit U>
|
||||
struct scaled_unit;
|
||||
@@ -144,8 +143,8 @@ inline constexpr bool is_specialization_of_prefixed_unit<prefixed_unit<Symbol, M
|
||||
|
||||
template<typename T>
|
||||
requires requires(T* t) { is_unit_impl(t); } && (!is_specialization_of_named_unit<T>) &&
|
||||
(!is_specialization_of_prefixed_unit<T>)
|
||||
struct is_unit<T> : std::true_type {};
|
||||
(!is_specialization_of_prefixed_unit<T>)
|
||||
inline constexpr bool is_unit<T> = true;
|
||||
|
||||
template<Unit U>
|
||||
[[nodiscard]] consteval bool has_associated_quantity(U);
|
||||
@@ -197,7 +196,7 @@ concept UnitOf =
|
||||
|
||||
namespace detail {
|
||||
|
||||
[[nodiscard]] consteval bool have_same_canonical_reference_unit(Unit auto u1, Unit auto u2);
|
||||
[[nodiscard]] consteval auto have_same_canonical_reference_unit(Unit auto u1, Unit auto u2);
|
||||
|
||||
}
|
||||
|
||||
@@ -210,7 +209,7 @@ namespace detail {
|
||||
MP_UNITS_EXPORT template<typename U, auto U2, auto QS>
|
||||
concept UnitCompatibleWith =
|
||||
Unit<U> && Unit<MP_UNITS_REMOVE_CONST(decltype(U2))> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> &&
|
||||
(!AssociatedUnit<U> || UnitOf<U, QS>)&&detail::have_same_canonical_reference_unit(U{}, U2);
|
||||
(!AssociatedUnit<U> || UnitOf<U, QS>)&&decltype(detail::have_same_canonical_reference_unit(U{}, U2))::value;
|
||||
|
||||
|
||||
} // namespace mp_units
|
||||
@@ -116,8 +116,7 @@ struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::durati
|
||||
template<QuantityOf<isq::time> Q>
|
||||
[[nodiscard]] constexpr auto to_chrono_duration(const Q& q)
|
||||
{
|
||||
constexpr auto canonical = get_canonical_unit(Q::unit);
|
||||
constexpr detail::ratio r = detail::as_ratio(canonical.mag);
|
||||
constexpr detail::ratio r = detail::as_ratio(decltype(get_canonical_unit(Q::unit))::mag);
|
||||
return std::chrono::duration<typename Q::rep, std::ratio<r.num, r.den>>{q};
|
||||
}
|
||||
|
||||
@@ -127,8 +126,7 @@ template<QuantityPointOf<isq::time> QP>
|
||||
{
|
||||
using clock = MP_UNITS_TYPENAME decltype(QP::absolute_point_origin)::clock;
|
||||
using rep = MP_UNITS_TYPENAME QP::rep;
|
||||
constexpr auto canonical = get_canonical_unit(QP::unit);
|
||||
constexpr detail::ratio r = detail::as_ratio(canonical.mag);
|
||||
constexpr detail::ratio r = detail::as_ratio(decltype(get_canonical_unit(QP::unit))::mag);
|
||||
using ret_type = std::chrono::time_point<clock, std::chrono::duration<rep, std::ratio<r.num, r.den>>>;
|
||||
return ret_type(to_chrono_duration(qp - qp.absolute_point_origin));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user