Merge remote-tracking branch 'mpusz/master' into master-msvc-194
This commit is contained in:
commit
1d0dbf48b1
78 files changed
+1750
-1017
No files matched your search
@@ -122,7 +122,7 @@ public:
|
||||
MP_UNITS_EXPORT_END
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_integer =
|
||||
constexpr bool is_integer =
|
||||
std::is_integral_v<T> && !std::is_same_v<T, bool> && !std::is_same_v<T, char> && !std::is_same_v<T, wchar_t>;
|
||||
|
||||
// Converts a character to ASCII. Returns a number > 127 on conversion failure.
|
||||
|
||||
@@ -76,6 +76,10 @@
|
||||
#if !defined MP_UNITS_HOSTED && defined __STDC_HOSTED__
|
||||
#define MP_UNITS_HOSTED __STDC_HOSTED__
|
||||
#endif
|
||||
|
||||
// workarounds for https://cplusplus.github.io/CWG/issues/2387.html
|
||||
#define MP_UNITS_INLINE inline
|
||||
|
||||
#if MP_UNITS_COMP_GCC
|
||||
|
||||
#define MP_UNITS_REMOVE_CONST(expr) std::remove_const_t<expr>
|
||||
|
||||
@@ -42,36 +42,26 @@ using has_common_type = typename has_common_type_impl<void, Ts...>::type;
|
||||
template<typename... Ts>
|
||||
constexpr bool has_common_type_v = has_common_type_impl<void, Ts...>::value;
|
||||
|
||||
template<typename T, typename Other>
|
||||
struct get_common_type : std::common_type<T, Other> {};
|
||||
|
||||
template<typename T, typename Other>
|
||||
using maybe_common_type =
|
||||
std::conditional_t<has_common_type_v<T, Other>, get_common_type<T, Other>, std::type_identity<T>>::type;
|
||||
std::conditional_t<has_common_type_v<T, Other>, std::common_type<T, Other>, std::type_identity<T>>::type;
|
||||
|
||||
/**
|
||||
* @brief Details about the conversion from one quantity to another.
|
||||
* @brief Type-related details about the conversion from one quantity to another
|
||||
*
|
||||
* This struct calculates the conversion factor that needs to be applied to a number,
|
||||
* in order to convert from one quantity to another. In addition to that, it also
|
||||
* helps to determine what representations to use at which step in the conversion process,
|
||||
* This trait helps to determine what representations to use at which step in the conversion process,
|
||||
* in order to avoid overflow and underflow while not causing excessive computations.
|
||||
*
|
||||
* @note This is a low-level facility.
|
||||
*
|
||||
* @tparam To a target quantity type to cast to
|
||||
* @tparam From a source quantity type to cast from
|
||||
* @tparam M common magnitude between the two quantities
|
||||
* @tparam Rep1 first quantity representation type
|
||||
* @tparam Rep2 second quantity representation type
|
||||
*/
|
||||
template<Quantity To, Quantity From>
|
||||
requires(castable(From::quantity_spec, To::quantity_spec))
|
||||
struct magnitude_conversion_traits {
|
||||
// scale the number
|
||||
static constexpr Magnitude auto c_mag = get_canonical_unit(From::unit).mag / get_canonical_unit(To::unit).mag;
|
||||
static constexpr Magnitude auto num = numerator(c_mag);
|
||||
static constexpr Magnitude auto den = denominator(c_mag);
|
||||
static constexpr Magnitude auto irr = c_mag * (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>;
|
||||
template<Magnitude auto M, typename Rep1, typename Rep2>
|
||||
struct conversion_type_traits {
|
||||
using c_rep_type = maybe_common_type<Rep1, Rep2>;
|
||||
using c_mag_type = common_magnitude_type<M>;
|
||||
using multiplier_type = conditional<
|
||||
treat_as_floating_point<c_rep_type>,
|
||||
// ensure that the multiplier is also floating-point
|
||||
@@ -80,11 +70,28 @@ struct magnitude_conversion_traits {
|
||||
std::common_type_t<c_mag_type, value_type_t<c_rep_type>>, std::common_type_t<c_mag_type, double>>,
|
||||
c_mag_type>;
|
||||
using c_type = maybe_common_type<c_rep_type, multiplier_type>;
|
||||
static constexpr auto val(Magnitude auto m) { return get_value<multiplier_type>(m); };
|
||||
static constexpr multiplier_type num_mult = val(num);
|
||||
static constexpr multiplier_type den_mult = val(den);
|
||||
static constexpr multiplier_type irr_mult = val(irr);
|
||||
static constexpr multiplier_type ratio = num_mult / den_mult * irr_mult;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Value-related details about the conversion from one quantity to another
|
||||
*
|
||||
* This trait provide ingredients to calculate the conversion factor that needs to be applied
|
||||
* to a number, in order to convert from one quantity to another.
|
||||
*
|
||||
* @note This is a low-level facility.
|
||||
*
|
||||
* @tparam M common magnitude between the two quantities
|
||||
* @tparam T common multiplier representation type
|
||||
*/
|
||||
template<Magnitude auto M, typename T>
|
||||
struct conversion_value_traits {
|
||||
static constexpr Magnitude auto num = numerator(M);
|
||||
static constexpr Magnitude auto den = denominator(M);
|
||||
static constexpr Magnitude auto irr = M * (den / num);
|
||||
static constexpr T num_mult = get_value<T>(num);
|
||||
static constexpr T den_mult = get_value<T>(den);
|
||||
static constexpr T irr_mult = get_value<T>(irr);
|
||||
static constexpr T ratio = num_mult / den_mult * irr_mult;
|
||||
};
|
||||
|
||||
|
||||
@@ -96,34 +103,45 @@ struct magnitude_conversion_traits {
|
||||
*
|
||||
* @tparam To a target quantity type to cast to
|
||||
*/
|
||||
template<Quantity To, typename From>
|
||||
requires Quantity<std::remove_cvref_t<From>> &&
|
||||
(castable(std::remove_reference_t<From>::quantity_spec, To::quantity_spec)) &&
|
||||
((std::remove_reference_t<From>::unit == To::unit &&
|
||||
std::constructible_from<typename To::rep, typename std::remove_reference_t<From>::rep>) ||
|
||||
(std::remove_reference_t<From>::unit != To::unit)) // && scalable_with_<typename To::rep>))
|
||||
template<Quantity To, typename FwdFrom, Quantity From = std::remove_cvref_t<FwdFrom>>
|
||||
requires(castable(From::quantity_spec, To::quantity_spec)) &&
|
||||
((From::unit == To::unit && std::constructible_from<typename To::rep, typename From::rep>) ||
|
||||
(From::unit != To::unit)) // && scalable_with_<typename To::rep>))
|
||||
// TODO how to constrain the second part here?
|
||||
[[nodiscard]] constexpr To sudo_cast(From&& q)
|
||||
[[nodiscard]] constexpr To sudo_cast(FwdFrom&& q)
|
||||
{
|
||||
constexpr auto q_unit = std::remove_reference_t<From>::unit;
|
||||
constexpr auto q_unit = From::unit;
|
||||
if constexpr (q_unit == To::unit) {
|
||||
// no scaling of the number needed
|
||||
return {static_cast<To::rep>(std::forward<From>(q).numerical_value_is_an_implementation_detail_),
|
||||
return {static_cast<To::rep>(std::forward<FwdFrom>(q).numerical_value_is_an_implementation_detail_),
|
||||
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
|
||||
} else {
|
||||
constexpr Magnitude auto c_mag = get_canonical_unit(From::unit).mag / get_canonical_unit(To::unit).mag;
|
||||
using type_traits = conversion_type_traits<c_mag, typename From::rep, typename To::rep>;
|
||||
using multiplier_type = typename type_traits::multiplier_type;
|
||||
// TODO the below crashed nearly every compiler I tried it on
|
||||
// auto scale = [&](std::invocable<typename type_traits::c_type> auto func) {
|
||||
auto scale = [&](auto func) {
|
||||
auto res =
|
||||
static_cast<To::rep>(func(static_cast<type_traits::c_type>(q.numerical_value_is_an_implementation_detail_)));
|
||||
return To{res, To::reference};
|
||||
};
|
||||
|
||||
// scale the number
|
||||
using traits = magnitude_conversion_traits<To, std::remove_reference_t<From>>;
|
||||
if constexpr (std::is_floating_point_v<typename traits::multiplier_type>) {
|
||||
// this results in great assembly
|
||||
auto res = static_cast<To::rep>(static_cast<traits::c_type>(q.numerical_value_is_an_implementation_detail_) *
|
||||
traits::ratio);
|
||||
return {res, To::reference};
|
||||
} else {
|
||||
// this is slower but allows conversions like 2000 m -> 2 km without loosing data
|
||||
auto res = static_cast<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, To::reference};
|
||||
if constexpr (is_integral(c_mag))
|
||||
return scale([&](auto value) { return value * get_value<multiplier_type>(numerator(c_mag)); });
|
||||
else if constexpr (is_integral(pow<-1>(c_mag)))
|
||||
return scale([&](auto value) { return value / get_value<multiplier_type>(denominator(c_mag)); });
|
||||
else {
|
||||
using value_traits = conversion_value_traits<c_mag, multiplier_type>;
|
||||
if constexpr (std::is_floating_point_v<multiplier_type>)
|
||||
// this results in great assembly
|
||||
return scale([](auto value) { return value * value_traits::ratio; });
|
||||
else
|
||||
// this is slower but allows conversions like 2000 m -> 2 km without loosing data
|
||||
return scale(
|
||||
[](auto value) { return value * value_traits::num_mult / value_traits::den_mult * value_traits::irr_mult; });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,21 +155,18 @@ template<Quantity To, typename From>
|
||||
*
|
||||
* @tparam ToQP a target quantity point type to which to cast to
|
||||
*/
|
||||
template<QuantityPoint ToQP, typename FromQP>
|
||||
requires QuantityPoint<std::remove_cvref_t<FromQP>> &&
|
||||
(castable(std::remove_reference_t<FromQP>::quantity_spec, ToQP::quantity_spec)) &&
|
||||
(detail::same_absolute_point_origins(ToQP::point_origin, std::remove_reference_t<FromQP>::point_origin)) &&
|
||||
((std::remove_reference_t<FromQP>::unit == ToQP::unit &&
|
||||
std::constructible_from<typename ToQP::rep, typename std::remove_reference_t<FromQP>::rep>) ||
|
||||
(std::remove_reference_t<FromQP>::unit != ToQP::unit))
|
||||
[[nodiscard]] constexpr QuantityPoint auto sudo_cast(FromQP&& qp)
|
||||
template<QuantityPoint ToQP, typename FwdFromQP, QuantityPoint FromQP = std::remove_cvref_t<FwdFromQP>>
|
||||
requires(castable(FromQP::quantity_spec, ToQP::quantity_spec)) &&
|
||||
(detail::same_absolute_point_origins(ToQP::point_origin, FromQP::point_origin)) &&
|
||||
((FromQP::unit == ToQP::unit && std::constructible_from<typename ToQP::rep, typename FromQP::rep>) ||
|
||||
(FromQP::unit != ToQP::unit))
|
||||
[[nodiscard]] constexpr QuantityPoint auto sudo_cast(FwdFromQP&& qp)
|
||||
{
|
||||
using qp_type = std::remove_reference_t<FromQP>;
|
||||
if constexpr (is_same_v<std::remove_const_t<decltype(ToQP::point_origin)>,
|
||||
std::remove_const_t<decltype(qp_type::point_origin)>>) {
|
||||
std::remove_const_t<decltype(FromQP::point_origin)>>) {
|
||||
return quantity_point{
|
||||
sudo_cast<typename ToQP::quantity_type>(std::forward<FromQP>(qp).quantity_from(qp_type::point_origin)),
|
||||
qp_type::point_origin};
|
||||
sudo_cast<typename ToQP::quantity_type>(std::forward<FwdFromQP>(qp).quantity_from(FromQP::point_origin)),
|
||||
FromQP::point_origin};
|
||||
} else {
|
||||
// it's unclear how hard we should try to avoid truncation here. For now, the only corner case we cater for,
|
||||
// is when the range of the quantity type of at most one of QP or ToQP doesn't cover the offset between the
|
||||
@@ -163,23 +178,26 @@ template<QuantityPoint ToQP, typename FromQP>
|
||||
// (c) add/subtract the origin difference
|
||||
// In the following, we carefully select the order of these three operations: each of (a) and (b) is scheduled
|
||||
// either before or after (c), such that (c) acts on the largest range possible among all combination of source
|
||||
// and target unit and represenation.
|
||||
using traits = magnitude_conversion_traits<typename ToQP::quantity_type, typename qp_type::quantity_type>;
|
||||
using c_rep_type = typename traits::c_rep_type;
|
||||
if constexpr (traits::num_mult * traits::irr_mult > traits::den_mult) {
|
||||
// and target unit and representation.
|
||||
constexpr Magnitude auto c_mag = get_canonical_unit(FromQP::unit).mag / get_canonical_unit(ToQP::unit).mag;
|
||||
using type_traits = conversion_type_traits<c_mag, typename FromQP::rep, typename ToQP::rep>;
|
||||
using value_traits = conversion_value_traits<c_mag, typename type_traits::multiplier_type>;
|
||||
using c_rep_type = typename type_traits::c_rep_type;
|
||||
if constexpr (value_traits::num_mult * value_traits::irr_mult > value_traits::den_mult) {
|
||||
// original unit had a larger unit magnitude; if we first convert to the common representation but retain the
|
||||
// unit, we obtain the largest possible range while not causing truncation of fractional values. This is optimal
|
||||
// for the offset computation.
|
||||
return sudo_cast<ToQP>(
|
||||
sudo_cast<quantity_point<qp_type::reference, qp_type::point_origin, c_rep_type>>(std::forward<FromQP>(qp))
|
||||
sudo_cast<quantity_point<FromQP::reference, FromQP::point_origin, c_rep_type>>(std::forward<FwdFromQP>(qp))
|
||||
.point_for(ToQP::point_origin));
|
||||
} else {
|
||||
// new unit may have a larger unit magnitude; we first need to convert to the new unit (potentially causing
|
||||
// truncation, but no more than if we did the conversion later), but make sure we keep the larger of the two
|
||||
// representation types. Then, we can perform the offset computation.
|
||||
return sudo_cast<ToQP>(sudo_cast<quantity_point<make_reference(qp_type::quantity_spec, ToQP::unit),
|
||||
qp_type::point_origin, c_rep_type>>(std::forward<FromQP>(qp))
|
||||
.point_for(ToQP::point_origin));
|
||||
return sudo_cast<ToQP>(
|
||||
sudo_cast<quantity_point<make_reference(FromQP::quantity_spec, ToQP::unit), FromQP::point_origin, c_rep_type>>(
|
||||
std::forward<FwdFromQP>(qp))
|
||||
.point_for(ToQP::point_origin));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,28 +40,28 @@ namespace mp_units::detail {
|
||||
|
||||
template<std::intmax_t Value>
|
||||
requires(0 <= Value) && (Value < 10)
|
||||
inline constexpr basic_fixed_string superscript_number = u8"";
|
||||
constexpr basic_fixed_string superscript_number = u8"";
|
||||
|
||||
template<>
|
||||
inline constexpr basic_fixed_string superscript_number<0> = u8"\u2070";
|
||||
MP_UNITS_INLINE constexpr basic_fixed_string superscript_number<0> = u8"\u2070";
|
||||
template<>
|
||||
inline constexpr basic_fixed_string superscript_number<1> = u8"\u00b9";
|
||||
MP_UNITS_INLINE constexpr basic_fixed_string superscript_number<1> = u8"\u00b9";
|
||||
template<>
|
||||
inline constexpr basic_fixed_string superscript_number<2> = u8"\u00b2";
|
||||
MP_UNITS_INLINE constexpr basic_fixed_string superscript_number<2> = u8"\u00b2";
|
||||
template<>
|
||||
inline constexpr basic_fixed_string superscript_number<3> = u8"\u00b3";
|
||||
MP_UNITS_INLINE constexpr basic_fixed_string superscript_number<3> = u8"\u00b3";
|
||||
template<>
|
||||
inline constexpr basic_fixed_string superscript_number<4> = u8"\u2074";
|
||||
MP_UNITS_INLINE constexpr basic_fixed_string superscript_number<4> = u8"\u2074";
|
||||
template<>
|
||||
inline constexpr basic_fixed_string superscript_number<5> = u8"\u2075";
|
||||
MP_UNITS_INLINE constexpr basic_fixed_string superscript_number<5> = u8"\u2075";
|
||||
template<>
|
||||
inline constexpr basic_fixed_string superscript_number<6> = u8"\u2076";
|
||||
MP_UNITS_INLINE constexpr basic_fixed_string superscript_number<6> = u8"\u2076";
|
||||
template<>
|
||||
inline constexpr basic_fixed_string superscript_number<7> = u8"\u2077";
|
||||
MP_UNITS_INLINE constexpr basic_fixed_string superscript_number<7> = u8"\u2077";
|
||||
template<>
|
||||
inline constexpr basic_fixed_string superscript_number<8> = u8"\u2078";
|
||||
MP_UNITS_INLINE constexpr basic_fixed_string superscript_number<8> = u8"\u2078";
|
||||
template<>
|
||||
inline constexpr basic_fixed_string superscript_number<9> = u8"\u2079";
|
||||
MP_UNITS_INLINE constexpr basic_fixed_string superscript_number<9> = u8"\u2079";
|
||||
|
||||
inline constexpr symbol_text superscript_minus(u8"\u207b", "-");
|
||||
|
||||
|
||||
@@ -40,10 +40,10 @@ MP_UNITS_DIAGNOSTIC_IGNORE_EXPR_ALWAYS_TF
|
||||
namespace mp_units::detail {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_type_list = false;
|
||||
constexpr bool is_type_list = false;
|
||||
|
||||
template<template<typename...> typename T, typename... Types>
|
||||
inline constexpr bool is_type_list<T<Types...>> = true;
|
||||
constexpr bool is_type_list<T<Types...>> = true;
|
||||
|
||||
template<typename T>
|
||||
concept TypeList = is_type_list<T>;
|
||||
@@ -56,7 +56,7 @@ template<template<typename...> typename List, typename... Types>
|
||||
struct type_list_size_impl<List<Types...>> : std::integral_constant<std::size_t, sizeof...(Types)> {};
|
||||
|
||||
template<TypeList List>
|
||||
inline constexpr std::size_t type_list_size = type_list_size_impl<List>::value;
|
||||
constexpr std::size_t type_list_size = type_list_size_impl<List>::value;
|
||||
|
||||
// map
|
||||
template<typename T, template<typename...> typename To>
|
||||
|
||||
@@ -60,26 +60,26 @@ using conditional = detail::conditional_impl<B>::template type<T, F>;
|
||||
|
||||
// is_same
|
||||
template<class T, class U>
|
||||
inline constexpr bool is_same_v = false;
|
||||
constexpr bool is_same_v = false;
|
||||
|
||||
template<class T>
|
||||
inline constexpr bool is_same_v<T, T> = true;
|
||||
constexpr bool is_same_v<T, T> = true;
|
||||
|
||||
template<class T, class U>
|
||||
using is_same = std::bool_constant<is_same_v<T, U>>;
|
||||
|
||||
// is_specialization_of
|
||||
template<typename T, template<typename...> typename Type>
|
||||
inline constexpr bool is_specialization_of = false;
|
||||
constexpr bool is_specialization_of = false;
|
||||
|
||||
template<typename... Params, template<typename...> typename Type>
|
||||
inline constexpr bool is_specialization_of<Type<Params...>, Type> = true;
|
||||
constexpr bool is_specialization_of<Type<Params...>, Type> = true;
|
||||
|
||||
template<typename T, template<auto...> typename Type>
|
||||
inline constexpr bool is_specialization_of_v = false;
|
||||
constexpr bool is_specialization_of_v = false;
|
||||
|
||||
template<auto... Params, template<auto...> typename Type>
|
||||
inline constexpr bool is_specialization_of_v<Type<Params...>, Type> = true;
|
||||
constexpr bool is_specialization_of_v<Type<Params...>, Type> = true;
|
||||
|
||||
MP_UNITS_EXPORT_END
|
||||
|
||||
@@ -92,8 +92,7 @@ void to_base_specialization_of(const volatile Type<Params...>*);
|
||||
} // namespace detail
|
||||
|
||||
template<typename T, template<typename...> typename Type>
|
||||
inline constexpr bool is_derived_from_specialization_of =
|
||||
requires(T* t) { detail::to_base_specialization_of<Type>(t); };
|
||||
constexpr bool is_derived_from_specialization_of = requires(T* t) { detail::to_base_specialization_of<Type>(t); };
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
@@ -39,34 +39,29 @@ namespace mp_units {
|
||||
|
||||
template<Reference R>
|
||||
struct delta_ {
|
||||
template<typename Rep>
|
||||
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
|
||||
[[nodiscard]] constexpr quantity<MP_UNITS_EXPRESSION_WORKAROUND(R{}), std::remove_cvref_t<Rep>> operator()(
|
||||
Rep&& lhs) const
|
||||
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
|
||||
[[nodiscard]] constexpr quantity<MP_UNITS_EXPRESSION_WORKAROUND(R{}), Rep> operator()(FwdRep&& lhs) const
|
||||
{
|
||||
return quantity{std::forward<Rep>(lhs), R{}};
|
||||
return quantity{std::forward<FwdRep>(lhs), R{}};
|
||||
}
|
||||
};
|
||||
|
||||
template<Reference R>
|
||||
struct absolute_ {
|
||||
template<typename Rep>
|
||||
requires RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
|
||||
[[nodiscard]] constexpr quantity_point<MP_UNITS_EXPRESSION_WORKAROUND(R{}), default_point_origin(R{}),
|
||||
std::remove_cvref_t<Rep>>
|
||||
operator()(Rep&& lhs) const
|
||||
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
|
||||
[[nodiscard]] constexpr quantity_point<MP_UNITS_EXPRESSION_WORKAROUND(R{}), default_point_origin(R{}), Rep> operator()(FwdRep&& lhs) const
|
||||
{
|
||||
return quantity_point{quantity{std::forward<Rep>(lhs), R{}}};
|
||||
return quantity_point{quantity{std::forward<FwdRep>(lhs), R{}}};
|
||||
}
|
||||
};
|
||||
|
||||
MP_UNITS_EXPORT_BEGIN
|
||||
|
||||
template<Reference auto R>
|
||||
inline constexpr delta_<MP_UNITS_REMOVE_CONST(decltype(R))> delta{};
|
||||
constexpr delta_<MP_UNITS_REMOVE_CONST(decltype(R))> delta{};
|
||||
|
||||
template<Reference auto R>
|
||||
inline constexpr absolute_<MP_UNITS_REMOVE_CONST(decltype(R))> absolute{};
|
||||
constexpr absolute_<MP_UNITS_REMOVE_CONST(decltype(R))> absolute{};
|
||||
|
||||
MP_UNITS_EXPORT_END
|
||||
|
||||
|
||||
@@ -50,11 +50,11 @@ MP_UNITS_EXPORT_BEGIN
|
||||
* @tparam Rep a representation type for which a type trait is defined
|
||||
*/
|
||||
template<typename Rep>
|
||||
inline constexpr bool treat_as_floating_point = std::is_floating_point_v<Rep>;
|
||||
constexpr bool treat_as_floating_point = std::is_floating_point_v<Rep>;
|
||||
|
||||
template<typename Rep>
|
||||
requires requires { typename wrapped_type_t<Rep>; }
|
||||
inline constexpr bool treat_as_floating_point<Rep> = treat_as_floating_point<wrapped_type_t<Rep>>;
|
||||
constexpr bool treat_as_floating_point<Rep> = treat_as_floating_point<wrapped_type_t<Rep>>;
|
||||
|
||||
/**
|
||||
* @brief Specifies a type to have a scalar character
|
||||
@@ -62,7 +62,7 @@ inline constexpr bool treat_as_floating_point<Rep> = treat_as_floating_point<wra
|
||||
* A scalar is a physical quantity that has magnitude but no direction.
|
||||
*/
|
||||
template<typename Rep>
|
||||
inline constexpr bool is_scalar = std::is_floating_point_v<Rep> || (std::is_integral_v<Rep> && !is_same_v<Rep, bool>);
|
||||
constexpr bool is_scalar = std::is_floating_point_v<Rep> || (std::is_integral_v<Rep> && !is_same_v<Rep, bool>);
|
||||
|
||||
/**
|
||||
* @brief Specifies a type to have a vector character
|
||||
@@ -76,11 +76,11 @@ inline constexpr bool is_scalar = std::is_floating_point_v<Rep> || (std::is_inte
|
||||
* @code{.cpp}
|
||||
* template<class T>
|
||||
* requires mp_units::is_scalar<T>
|
||||
* inline constexpr bool mp_units::is_vector<T> = true;
|
||||
* constexpr bool mp_units::is_vector<T> = true;
|
||||
* @endcode
|
||||
*/
|
||||
template<typename Rep>
|
||||
inline constexpr bool is_vector = false;
|
||||
constexpr bool is_vector = false;
|
||||
|
||||
/**
|
||||
* @brief Specifies a type to have a tensor character
|
||||
@@ -91,7 +91,7 @@ inline constexpr bool is_vector = false;
|
||||
* Similarly to `is_vector` a partial specialization is needed in such cases.
|
||||
*/
|
||||
template<typename Rep>
|
||||
inline constexpr bool is_tensor = false;
|
||||
constexpr bool is_tensor = false;
|
||||
|
||||
/**
|
||||
* @brief A type trait that defines zero, one, min, and max for a representation type
|
||||
|
||||
@@ -53,7 +53,7 @@ template<symbol_text Symbol>
|
||||
void to_base_specialization_of_base_dimension(const volatile base_dimension<Symbol>*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_base_dimension =
|
||||
constexpr bool is_derived_from_specialization_of_base_dimension =
|
||||
requires(T* type) { to_base_specialization_of_base_dimension(type); };
|
||||
|
||||
/**
|
||||
@@ -68,16 +68,16 @@ template<typename T>
|
||||
struct is_dimension_one : std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_power_of_dim = requires {
|
||||
constexpr bool is_power_of_dim = requires {
|
||||
requires is_specialization_of_power<T> &&
|
||||
(BaseDimension<typename T::factor> || is_dimension_one<typename T::factor>::value);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_per_of_dims = false;
|
||||
constexpr bool is_per_of_dims = false;
|
||||
|
||||
template<typename... Ts>
|
||||
inline constexpr bool is_per_of_dims<per<Ts...>> =
|
||||
constexpr bool is_per_of_dims<per<Ts...>> =
|
||||
(... && (BaseDimension<Ts> || is_dimension_one<Ts>::value || is_power_of_dim<Ts>));
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -57,37 +57,37 @@ struct per {};
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_per = false;
|
||||
constexpr bool is_specialization_of_per = false;
|
||||
|
||||
template<typename... Ts>
|
||||
inline constexpr bool is_specialization_of_per<per<Ts...>> = true;
|
||||
constexpr bool is_specialization_of_per<per<Ts...>> = true;
|
||||
|
||||
template<int Num, int... Den>
|
||||
inline constexpr bool valid_ratio = true;
|
||||
constexpr bool valid_ratio = true;
|
||||
|
||||
template<int... Den>
|
||||
inline constexpr bool valid_ratio<0, Den...> = false;
|
||||
constexpr bool valid_ratio<0, Den...> = false;
|
||||
|
||||
template<int Num>
|
||||
inline constexpr bool valid_ratio<Num, 0> = false;
|
||||
constexpr bool valid_ratio<Num, 0> = false;
|
||||
|
||||
template<>
|
||||
inline constexpr bool valid_ratio<0, 0> = false;
|
||||
MP_UNITS_INLINE constexpr bool valid_ratio<0, 0> = false;
|
||||
|
||||
template<int Num, int... Den>
|
||||
inline constexpr bool positive_ratio = gt_zero<Num>;
|
||||
constexpr bool positive_ratio = gt_zero<Num>;
|
||||
|
||||
template<int Num, int Den>
|
||||
inline constexpr bool positive_ratio<Num, Den> = gt_zero<Num * Den>;
|
||||
constexpr bool positive_ratio<Num, Den> = gt_zero<Num * Den>;
|
||||
|
||||
template<int Num, int... Den>
|
||||
inline constexpr bool ratio_one = false;
|
||||
constexpr bool ratio_one = false;
|
||||
|
||||
template<>
|
||||
inline constexpr bool ratio_one<1> = true;
|
||||
MP_UNITS_INLINE constexpr bool ratio_one<1> = true;
|
||||
|
||||
template<int N>
|
||||
inline constexpr bool ratio_one<N, N> = true;
|
||||
constexpr bool ratio_one<N, N> = true;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -127,10 +127,10 @@ using expr_type = detail::expr_type_impl<T>::type;
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_power = false;
|
||||
constexpr bool is_specialization_of_power = false;
|
||||
|
||||
template<typename F, int... Ints>
|
||||
inline constexpr bool is_specialization_of_power<power<F, Ints...>> = true;
|
||||
constexpr bool is_specialization_of_power<power<F, Ints...>> = true;
|
||||
|
||||
template<typename T, ratio R>
|
||||
consteval auto power_or_T_impl()
|
||||
@@ -508,10 +508,10 @@ concept expr_type_projectable = (requires { typename Proj<T>; } ||
|
||||
(is_specialization_of_power<T> && requires { typename Proj<typename T::factor>; }));
|
||||
|
||||
template<typename T, template<typename> typename Proj>
|
||||
inline constexpr bool expr_projectable_impl = false;
|
||||
constexpr bool expr_projectable_impl = false;
|
||||
|
||||
template<typename... Ts, template<typename> typename Proj>
|
||||
inline constexpr bool expr_projectable_impl<type_list<Ts...>, Proj> = (... && expr_type_projectable<Ts, Proj>);
|
||||
constexpr bool expr_projectable_impl<type_list<Ts...>, Proj> = (... && expr_type_projectable<Ts, Proj>);
|
||||
|
||||
template<typename T, template<typename> typename Proj>
|
||||
concept expr_projectable = requires {
|
||||
|
||||
@@ -59,10 +59,10 @@ using factorizer = wheel_factorizer<4>;
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_magnitude = false;
|
||||
constexpr bool is_magnitude = false;
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_magnitude = false;
|
||||
constexpr bool is_specialization_of_magnitude = false;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -87,7 +87,7 @@ concept Magnitude = detail::is_magnitude<T>;
|
||||
// void to_base_specialization_of_constant(const volatile constant<V>*);
|
||||
|
||||
// template<typename T>
|
||||
// inline constexpr bool is_derived_from_specialization_of_constant =
|
||||
// constexpr bool is_derived_from_specialization_of_constant =
|
||||
// requires(T * t) { to_base_specialization_of_constant(t); };
|
||||
|
||||
// } // namespace detail
|
||||
@@ -142,7 +142,7 @@ concept Magnitude = detail::is_magnitude<T>;
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_named_magnitude = Magnitude<T> && !detail::is_specialization_of_magnitude<T>;
|
||||
constexpr bool is_named_magnitude = Magnitude<T> && !detail::is_specialization_of_magnitude<T>;
|
||||
|
||||
}
|
||||
|
||||
@@ -178,10 +178,10 @@ struct power_v {
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_power_v = false;
|
||||
constexpr bool is_specialization_of_power_v = false;
|
||||
|
||||
template<auto V, int... Ints>
|
||||
inline constexpr bool is_specialization_of_power_v<power_v<V, Ints...>> = true;
|
||||
constexpr bool is_specialization_of_power_v<power_v<V, Ints...>> = true;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -572,13 +572,13 @@ namespace detail {
|
||||
// }
|
||||
|
||||
// template<MagnitudeSpec auto... Elements>
|
||||
// inline constexpr bool all_elements_valid = (is_valid_element(Elements) && ...);
|
||||
// constexpr bool all_elements_valid = (is_valid_element(Elements) && ...);
|
||||
|
||||
// template<MagnitudeSpec auto... Elements>
|
||||
// inline constexpr bool all_elements_in_order = strictly_increasing(get_base_value(Elements)...);
|
||||
// constexpr bool all_elements_in_order = strictly_increasing(get_base_value(Elements)...);
|
||||
|
||||
// template<MagnitudeSpec auto... Elements>
|
||||
// inline constexpr bool is_element_pack_valid = all_elements_valid<Elements...> && all_elements_in_order<Elements...>;
|
||||
// constexpr bool is_element_pack_valid = all_elements_valid<Elements...> && all_elements_in_order<Elements...>;
|
||||
|
||||
[[nodiscard]] consteval bool is_rational(MagnitudeSpec auto element)
|
||||
{
|
||||
@@ -707,15 +707,15 @@ template<auto... Ms>
|
||||
void to_base_specialization_of_magnitude(const volatile magnitude<Ms...>*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_magnitude =
|
||||
constexpr bool is_derived_from_specialization_of_magnitude =
|
||||
requires(T* type) { to_base_specialization_of_magnitude(type); };
|
||||
|
||||
template<typename T>
|
||||
requires is_derived_from_specialization_of_magnitude<T>
|
||||
inline constexpr bool is_magnitude<T> = true;
|
||||
constexpr bool is_magnitude<T> = true;
|
||||
|
||||
template<auto... Ms>
|
||||
inline constexpr bool is_specialization_of_magnitude<magnitude<Ms...>> = true;
|
||||
constexpr bool is_specialization_of_magnitude<magnitude<Ms...>> = true;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -882,7 +882,7 @@ using common_magnitude_type = decltype(common_magnitude_type_impl(M));
|
||||
//
|
||||
// WARNING: The program behaviour will be undefined if you provide a wrong answer, so check your math!
|
||||
MP_UNITS_EXPORT template<std::intmax_t N>
|
||||
inline constexpr std::optional<std::intmax_t> known_first_factor = std::nullopt;
|
||||
constexpr std::optional<std::intmax_t> known_first_factor = std::nullopt;
|
||||
|
||||
namespace detail {
|
||||
|
||||
@@ -915,7 +915,7 @@ struct prime_factorization<1> {
|
||||
};
|
||||
|
||||
template<std::intmax_t N>
|
||||
inline constexpr auto prime_factorization_v = prime_factorization<N>::value;
|
||||
constexpr auto prime_factorization_v = prime_factorization<N>::value;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -927,18 +927,18 @@ inline constexpr auto prime_factorization_v = prime_factorization<N>::value;
|
||||
*/
|
||||
MP_UNITS_EXPORT template<std::intmax_t V>
|
||||
requires detail::gt_zero<V>
|
||||
inline constexpr Magnitude auto mag = detail::prime_factorization_v<V>;
|
||||
constexpr Magnitude auto mag = detail::prime_factorization_v<V>;
|
||||
|
||||
MP_UNITS_EXPORT template<std::intmax_t N, std::intmax_t D>
|
||||
requires detail::gt_zero<N>
|
||||
inline constexpr Magnitude auto mag_ratio = detail::prime_factorization_v<N> / detail::prime_factorization_v<D>;
|
||||
constexpr Magnitude auto mag_ratio = detail::prime_factorization_v<N> / detail::prime_factorization_v<D>;
|
||||
|
||||
/**
|
||||
* @brief Create a Magnitude which is some rational number raised to a rational power.
|
||||
*/
|
||||
MP_UNITS_EXPORT template<std::intmax_t Base, std::intmax_t Pow>
|
||||
requires detail::gt_zero<Base>
|
||||
inline constexpr Magnitude auto mag_power = pow<Pow>(mag<Base>);
|
||||
constexpr Magnitude auto mag_power = pow<Pow>(mag<Base>);
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
@@ -168,22 +168,23 @@ public:
|
||||
quantity(quantity&&) = default;
|
||||
~quantity() = default;
|
||||
|
||||
template<typename Value, Reference R2>
|
||||
requires detail::SameValueAs<R2{}, R, std::remove_cvref_t<Value>, Rep>
|
||||
constexpr quantity(Value&& v, R2) : numerical_value_is_an_implementation_detail_(std::forward<Value>(v))
|
||||
template<typename FwdValue, Reference R2>
|
||||
requires detail::SameValueAs<R2{}, R, std::remove_cvref_t<FwdValue>, Rep>
|
||||
constexpr quantity(FwdValue&& v, R2) : numerical_value_is_an_implementation_detail_(std::forward<FwdValue>(v))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Value, Reference R2>
|
||||
requires(!detail::SameValueAs<R2{}, R, std::remove_cvref_t<Value>, Rep>) &&
|
||||
detail::QuantityConvertibleTo<quantity<R2{}, std::remove_cvref_t<Value>>, quantity>
|
||||
constexpr quantity(Value&& v, R2) : quantity(quantity<R2{}, std::remove_cvref_t<Value>>{std::forward<Value>(v), R2{}})
|
||||
template<typename FwdValue, Reference R2, typename Value = std::remove_cvref_t<FwdValue>>
|
||||
requires(!detail::SameValueAs<R2{}, R, Value, Rep>) &&
|
||||
detail::QuantityConvertibleTo<quantity<R2{}, Value>, quantity>
|
||||
constexpr quantity(FwdValue&& v, R2) : quantity(quantity<R2{}, Value>{std::forward<FwdValue>(v), R2{}})
|
||||
{
|
||||
}
|
||||
|
||||
template<detail::ValuePreservingTo<Rep> Value>
|
||||
template<detail::ValuePreservingTo<Rep> FwdValue>
|
||||
requires(unit == ::mp_units::one)
|
||||
constexpr explicit(false) quantity(Value&& v) : numerical_value_is_an_implementation_detail_(std::forward<Value>(v))
|
||||
constexpr explicit(false) quantity(FwdValue&& v) :
|
||||
numerical_value_is_an_implementation_detail_(std::forward<FwdValue>(v))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -209,11 +210,11 @@ public:
|
||||
quantity& operator=(const quantity&) = default;
|
||||
quantity& operator=(quantity&&) = default;
|
||||
|
||||
template<detail::ValuePreservingTo<Rep> Value>
|
||||
template<detail::ValuePreservingTo<Rep> FwdValue>
|
||||
requires(unit == ::mp_units::one)
|
||||
constexpr quantity& operator=(Value&& v)
|
||||
constexpr quantity& operator=(FwdValue&& v)
|
||||
{
|
||||
numerical_value_is_an_implementation_detail_ = std::forward<Value>(v);
|
||||
numerical_value_is_an_implementation_detail_ = std::forward<FwdValue>(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -355,16 +356,16 @@ public:
|
||||
return ::mp_units::quantity{-numerical_value_is_an_implementation_detail_, reference};
|
||||
}
|
||||
|
||||
template<typename Q>
|
||||
friend constexpr decltype(auto) operator++(Q&& q)
|
||||
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && requires(rep v) {
|
||||
template<typename FwdQ, std::derived_from<quantity> Q = std::remove_cvref_t<FwdQ>>
|
||||
friend constexpr decltype(auto) operator++(FwdQ&& q)
|
||||
requires requires(rep v) {
|
||||
{
|
||||
++v
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
{
|
||||
++q.numerical_value_is_an_implementation_detail_;
|
||||
return std::forward<Q>(q);
|
||||
return std::forward<FwdQ>(q);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto operator++(int)
|
||||
@@ -377,16 +378,16 @@ public:
|
||||
return ::mp_units::quantity{numerical_value_is_an_implementation_detail_++, reference};
|
||||
}
|
||||
|
||||
template<typename Q>
|
||||
friend constexpr decltype(auto) operator--(Q&& q)
|
||||
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && requires(rep v) {
|
||||
template<typename FwdQ, std::derived_from<quantity> Q = std::remove_cvref_t<FwdQ>>
|
||||
friend constexpr decltype(auto) operator--(FwdQ&& q)
|
||||
requires requires(rep v) {
|
||||
{
|
||||
--v
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
{
|
||||
--q.numerical_value_is_an_implementation_detail_;
|
||||
return std::forward<Q>(q);
|
||||
return std::forward<FwdQ>(q);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto operator--(int)
|
||||
@@ -400,99 +401,94 @@ public:
|
||||
}
|
||||
|
||||
// compound assignment operators
|
||||
template<typename Q>
|
||||
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && requires(rep a, rep b) {
|
||||
template<typename FwdQ, std::derived_from<quantity> Q = std::remove_cvref_t<FwdQ>>
|
||||
requires requires(rep a, rep b) {
|
||||
{
|
||||
a += b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator+=(Q&& lhs, const quantity& rhs)
|
||||
friend constexpr decltype(auto) operator+=(FwdQ&& lhs, const quantity& rhs)
|
||||
{
|
||||
lhs.numerical_value_is_an_implementation_detail_ += rhs.numerical_value_is_an_implementation_detail_;
|
||||
return std::forward<Q>(lhs);
|
||||
return std::forward<FwdQ>(lhs);
|
||||
}
|
||||
|
||||
template<typename Q>
|
||||
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && requires(rep a, rep b) {
|
||||
template<typename FwdQ, std::derived_from<quantity> Q = std::remove_cvref_t<FwdQ>>
|
||||
requires requires(rep a, rep b) {
|
||||
{
|
||||
a -= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator-=(Q&& lhs, const quantity& rhs)
|
||||
friend constexpr decltype(auto) operator-=(FwdQ&& lhs, const quantity& rhs)
|
||||
{
|
||||
lhs.numerical_value_is_an_implementation_detail_ -= rhs.numerical_value_is_an_implementation_detail_;
|
||||
return std::forward<Q>(lhs);
|
||||
return std::forward<FwdQ>(lhs);
|
||||
}
|
||||
|
||||
template<typename Q>
|
||||
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && (!treat_as_floating_point<rep>) &&
|
||||
requires(rep a, rep b) {
|
||||
{
|
||||
a %= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator%=(Q&& lhs, const quantity& rhs)
|
||||
template<typename FwdQ, std::derived_from<quantity> Q = std::remove_cvref_t<FwdQ>>
|
||||
requires(!treat_as_floating_point<rep>) && requires(rep a, rep b) {
|
||||
{
|
||||
a %= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator%=(FwdQ&& lhs, const quantity& rhs)
|
||||
|
||||
{
|
||||
MP_UNITS_EXPECTS_DEBUG(rhs != zero());
|
||||
lhs.numerical_value_is_an_implementation_detail_ %= rhs.numerical_value_is_an_implementation_detail_;
|
||||
return std::forward<Q>(lhs);
|
||||
return std::forward<FwdQ>(lhs);
|
||||
}
|
||||
|
||||
template<typename Q, typename Value>
|
||||
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && (!Quantity<Value>) &&
|
||||
requires(rep a, const Value b) {
|
||||
{
|
||||
a *= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator*=(Q&& lhs, const Value& v)
|
||||
template<typename FwdQ, typename Value, std::derived_from<quantity> Q = std::remove_cvref_t<FwdQ>>
|
||||
requires(!Quantity<Value>) && requires(rep a, const Value b) {
|
||||
{
|
||||
a *= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator*=(FwdQ&& lhs, const Value& v)
|
||||
{
|
||||
lhs.numerical_value_is_an_implementation_detail_ = lhs.numerical_value_is_an_implementation_detail_ * v;
|
||||
return std::forward<Q>(lhs);
|
||||
return std::forward<FwdQ>(lhs);
|
||||
}
|
||||
|
||||
template<typename Q1, QuantityOf<dimensionless> Q2>
|
||||
requires std::derived_from<std::remove_cvref_t<Q1>, quantity> && (Q2::unit == ::mp_units::one) &&
|
||||
requires(rep a, const typename Q2::rep b) {
|
||||
{
|
||||
a *= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator*=(Q1&& lhs, const Q2& rhs)
|
||||
template<typename FwdQ1, QuantityOf<dimensionless> Q2, std::derived_from<quantity> Q1 = std::remove_cvref_t<FwdQ1>>
|
||||
requires(Q2::unit == ::mp_units::one) && requires(rep a, const typename Q2::rep b) {
|
||||
{
|
||||
a *= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator*=(FwdQ1&& lhs, const Q2& rhs)
|
||||
{
|
||||
lhs.numerical_value_is_an_implementation_detail_ =
|
||||
lhs.numerical_value_is_an_implementation_detail_ * rhs.numerical_value_is_an_implementation_detail_;
|
||||
return std::forward<Q1>(lhs);
|
||||
return std::forward<FwdQ1>(lhs);
|
||||
}
|
||||
|
||||
template<typename Q, typename Value>
|
||||
requires std::derived_from<std::remove_cvref_t<Q>, quantity> && (!Quantity<Value>) &&
|
||||
requires(rep a, const Value b) {
|
||||
{
|
||||
a /= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator/=(Q&& lhs, const Value& v)
|
||||
template<typename FwdQ, typename Value, std::derived_from<quantity> Q = std::remove_cvref_t<FwdQ>>
|
||||
requires(!Quantity<Value>) && requires(rep a, const Value b) {
|
||||
{
|
||||
a /= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator/=(FwdQ&& lhs, const Value& v)
|
||||
{
|
||||
MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero());
|
||||
lhs.numerical_value_is_an_implementation_detail_ = lhs.numerical_value_is_an_implementation_detail_ / v;
|
||||
return std::forward<Q>(lhs);
|
||||
return std::forward<FwdQ>(lhs);
|
||||
}
|
||||
|
||||
template<typename Q1, QuantityOf<dimensionless> Q2>
|
||||
requires std::derived_from<std::remove_cvref_t<Q1>, quantity> && (Q2::unit == ::mp_units::one) &&
|
||||
requires(rep a, const typename Q2::rep b) {
|
||||
{
|
||||
a /= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator/=(Q1&& lhs, const Q2& rhs)
|
||||
template<typename FwdQ1, QuantityOf<dimensionless> Q2, std::derived_from<quantity> Q1 = std::remove_cvref_t<FwdQ1>>
|
||||
requires(Q2::unit == ::mp_units::one) && requires(rep a, const typename Q2::rep b) {
|
||||
{
|
||||
a /= b
|
||||
} -> std::same_as<rep&>;
|
||||
}
|
||||
friend constexpr decltype(auto) operator/=(FwdQ1&& lhs, const Q2& rhs)
|
||||
{
|
||||
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
|
||||
lhs.numerical_value_is_an_implementation_detail_ =
|
||||
lhs.numerical_value_is_an_implementation_detail_ / rhs.numerical_value_is_an_implementation_detail_;
|
||||
return std::forward<Q1>(lhs);
|
||||
return std::forward<FwdQ1>(lhs);
|
||||
}
|
||||
|
||||
// binary operators on quantities
|
||||
|
||||
@@ -56,13 +56,11 @@ namespace mp_units {
|
||||
*
|
||||
* @tparam ToQS a quantity specification to use for a target quantity
|
||||
*/
|
||||
template<QuantitySpec auto ToQS, typename Q>
|
||||
requires Quantity<std::remove_cvref_t<Q>> &&
|
||||
detail::QuantitySpecCastableTo<std::remove_reference_t<Q>::quantity_spec, ToQS>
|
||||
[[nodiscard]] constexpr Quantity auto quantity_cast(Q&& q)
|
||||
template<QuantitySpec auto ToQS, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
requires detail::QuantitySpecCastableTo<Q::quantity_spec, ToQS>
|
||||
[[nodiscard]] constexpr Quantity auto quantity_cast(FwdQ&& q)
|
||||
{
|
||||
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
|
||||
make_reference(ToQS, std::remove_reference_t<Q>::unit)};
|
||||
return quantity{std::forward<FwdQ>(q).numerical_value_is_an_implementation_detail_, make_reference(ToQS, Q::unit)};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,13 +80,12 @@ template<QuantitySpec auto ToQS, typename Q>
|
||||
*
|
||||
* @tparam ToQS a quantity specification to use for a target quantity point
|
||||
*/
|
||||
template<QuantitySpec auto ToQS, typename QP>
|
||||
requires QuantityPoint<std::remove_cvref_t<QP>> &&
|
||||
detail::QuantitySpecCastableTo<std::remove_reference_t<QP>::quantity_spec, ToQS>
|
||||
[[nodiscard]] constexpr QuantityPoint auto quantity_cast(QP&& qp)
|
||||
template<QuantitySpec auto ToQS, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
requires detail::QuantitySpecCastableTo<QP::quantity_spec, ToQS>
|
||||
[[nodiscard]] constexpr QuantityPoint auto quantity_cast(FwdQP&& qp)
|
||||
{
|
||||
return QP{quantity_cast<ToQS>(std::forward<QP>(qp).quantity_from_origin_is_an_implementation_detail_),
|
||||
std::remove_reference_t<QP>::point_origin};
|
||||
return QP{quantity_cast<ToQS>(std::forward<FwdQP>(qp).quantity_from_origin_is_an_implementation_detail_),
|
||||
QP::point_origin};
|
||||
}
|
||||
|
||||
} // namespace mp_units
|
||||
@@ -40,7 +40,7 @@ template<auto R, typename Rep>
|
||||
void to_base_specialization_of_quantity(const volatile quantity<R, Rep>*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_quantity =
|
||||
constexpr bool is_derived_from_specialization_of_quantity =
|
||||
requires(T* type) { to_base_specialization_of_quantity(type); };
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace mp_units {
|
||||
namespace detail {
|
||||
|
||||
template<PointOrigin PO>
|
||||
inline constexpr bool is_specialization_of_zeroth_point_origin = false;
|
||||
constexpr bool is_specialization_of_zeroth_point_origin = false;
|
||||
|
||||
template<PointOrigin PO>
|
||||
[[nodiscard]] consteval bool is_zeroth_point_origin(PO)
|
||||
@@ -52,20 +52,16 @@ template<PointOrigin PO>
|
||||
}
|
||||
|
||||
struct point_origin_interface {
|
||||
template<PointOrigin PO, Quantity Q>
|
||||
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO::quantity_spec>
|
||||
[[nodiscard]] friend constexpr quantity_point<Q::reference, MP_UNITS_EXPRESSION_WORKAROUND(PO{}), typename Q::rep>
|
||||
operator+(PO, Q&& q)
|
||||
template<PointOrigin PO, typename FwdQ, QuantityOf<PO::quantity_spec> Q = std::remove_cvref_t<FwdQ>>
|
||||
[[nodiscard]] friend constexpr quantity_point<Q::reference, MP_UNITS_EXPRESSION_WORKAROUND(PO{}), typename Q::rep> operator+(PO, FwdQ&& q)
|
||||
{
|
||||
return quantity_point{std::forward<Q>(q), PO{}};
|
||||
return quantity_point{std::forward<FwdQ>(q), PO{}};
|
||||
}
|
||||
|
||||
template<Quantity Q, PointOrigin PO>
|
||||
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO::quantity_spec>
|
||||
[[nodiscard]] friend constexpr quantity_point<Q::reference, MP_UNITS_EXPRESSION_WORKAROUND(PO{}), typename Q::rep>
|
||||
operator+(Q&& q, PO po)
|
||||
template<Quantity FwdQ, PointOrigin PO, QuantityOf<PO::quantity_spec> Q = std::remove_cvref_t<FwdQ>>
|
||||
[[nodiscard]] friend constexpr quantity_point<Q::reference, MP_UNITS_EXPRESSION_WORKAROUND(PO{}), typename Q::rep> operator+(FwdQ&& q, PO po)
|
||||
{
|
||||
return po + std::forward<Q>(q);
|
||||
return po + std::forward<FwdQ>(q);
|
||||
}
|
||||
|
||||
template<PointOrigin PO, Quantity Q>
|
||||
@@ -132,12 +128,12 @@ template<QuantitySpec auto QS>
|
||||
struct zeroth_point_origin_ final : absolute_point_origin<QS> {};
|
||||
|
||||
MP_UNITS_EXPORT template<QuantitySpec auto QS>
|
||||
inline constexpr zeroth_point_origin_<QS> zeroth_point_origin;
|
||||
constexpr zeroth_point_origin_<QS> zeroth_point_origin;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<auto QS>
|
||||
inline constexpr bool is_specialization_of_zeroth_point_origin<zeroth_point_origin_<QS>> = true;
|
||||
constexpr bool is_specialization_of_zeroth_point_origin<zeroth_point_origin_<QS>> = true;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -208,27 +204,26 @@ public:
|
||||
quantity_point(quantity_point&&) = default;
|
||||
~quantity_point() = default;
|
||||
|
||||
template<typename Q>
|
||||
requires QuantityOf<std::remove_cvref_t<Q>, quantity_spec> && std::constructible_from<quantity_type, Q> &&
|
||||
(point_origin == default_point_origin(R)) && (implicitly_convertible(Q::quantity_spec, quantity_spec))
|
||||
constexpr explicit quantity_point(Q&& q) : quantity_from_origin_is_an_implementation_detail_(std::forward<Q>(q))
|
||||
template<typename FwdQ, QuantityOf<quantity_spec> Q = std::remove_cvref_t<FwdQ>>
|
||||
requires std::constructible_from<quantity_type, FwdQ> && (point_origin == default_point_origin(R)) &&
|
||||
(implicitly_convertible(Q::quantity_spec, quantity_spec))
|
||||
constexpr explicit quantity_point(FwdQ&& q) : quantity_from_origin_is_an_implementation_detail_(std::forward<FwdQ>(q))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Q>
|
||||
requires QuantityOf<std::remove_cvref_t<Q>, quantity_spec> && std::constructible_from<quantity_type, Q>
|
||||
constexpr quantity_point(Q&& q, decltype(PO)) : quantity_from_origin_is_an_implementation_detail_(std::forward<Q>(q))
|
||||
template<typename FwdQ, QuantityOf<quantity_spec> Q = std::remove_cvref_t<FwdQ>>
|
||||
requires std::constructible_from<quantity_type, FwdQ>
|
||||
constexpr quantity_point(FwdQ&& q, decltype(PO)) :
|
||||
quantity_from_origin_is_an_implementation_detail_(std::forward<FwdQ>(q))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Q, PointOrigin PO2>
|
||||
requires Quantity<std::remove_cvref_t<Q>> && std::constructible_from<quantity_type, Q> &&
|
||||
ReferenceOf<std::remove_const_t<decltype(std::remove_reference_t<Q>::reference)>, PO2::quantity_spec> &&
|
||||
detail::SameAbsolutePointOriginAs<PO2, PO>
|
||||
constexpr quantity_point(Q&& q, PO2) :
|
||||
template<typename FwdQ, PointOrigin PO2, QuantityOf<PO2::quantity_spec> Q = std::remove_cvref_t<FwdQ>>
|
||||
requires std::constructible_from<quantity_type, FwdQ> && detail::SameAbsolutePointOriginAs<PO2, PO>
|
||||
constexpr quantity_point(FwdQ&& q, PO2) :
|
||||
quantity_point(
|
||||
quantity_point<std::remove_reference_t<Q>::reference, PO2{}, typename std::remove_reference_t<Q>::rep>{
|
||||
std::forward<Q>(q), PO2{}})
|
||||
std::forward<FwdQ>(q), PO2{}})
|
||||
{
|
||||
}
|
||||
|
||||
@@ -299,7 +294,7 @@ public:
|
||||
#endif
|
||||
|
||||
template<PointOrigin PO2>
|
||||
requires requires { quantity_point{} - PO2{}; }
|
||||
requires requires(quantity_point qp) { qp - PO2{}; }
|
||||
[[nodiscard]] constexpr Quantity auto quantity_from(PO2) const
|
||||
{
|
||||
return *this - PO2{};
|
||||
@@ -414,13 +409,12 @@ public:
|
||||
}
|
||||
|
||||
// member unary operators
|
||||
template<typename QP>
|
||||
friend constexpr decltype(auto) operator++(QP&& qp)
|
||||
requires std::derived_from<std::remove_cvref_t<QP>, quantity_point> &&
|
||||
requires { ++qp.quantity_from_origin_is_an_implementation_detail_; }
|
||||
template<typename FwdQP, std::derived_from<quantity_point> QP = std::remove_cvref_t<FwdQP>>
|
||||
friend constexpr decltype(auto) operator++(FwdQP&& qp)
|
||||
requires requires { ++qp.quantity_from_origin_is_an_implementation_detail_; }
|
||||
{
|
||||
++qp.quantity_from_origin_is_an_implementation_detail_;
|
||||
return std::forward<QP>(qp);
|
||||
return std::forward<FwdQP>(qp);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr quantity_point operator++(int)
|
||||
@@ -429,13 +423,12 @@ public:
|
||||
return {quantity_from_origin_is_an_implementation_detail_++, PO};
|
||||
}
|
||||
|
||||
template<typename QP>
|
||||
friend constexpr decltype(auto) operator--(QP&& qp)
|
||||
requires std::derived_from<std::remove_cvref_t<QP>, quantity_point> &&
|
||||
requires { --qp.quantity_from_origin_is_an_implementation_detail_; }
|
||||
template<typename FwdQP, std::derived_from<quantity_point> QP = std::remove_cvref_t<FwdQP>>
|
||||
friend constexpr decltype(auto) operator--(FwdQP&& qp)
|
||||
requires requires { --qp.quantity_from_origin_is_an_implementation_detail_; }
|
||||
{
|
||||
--qp.quantity_from_origin_is_an_implementation_detail_;
|
||||
return std::forward<QP>(qp);
|
||||
return std::forward<FwdQP>(qp);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr quantity_point operator--(int)
|
||||
@@ -445,22 +438,20 @@ public:
|
||||
}
|
||||
|
||||
// compound assignment operators
|
||||
template<typename QP>
|
||||
requires std::derived_from<std::remove_cvref_t<QP>, quantity_point> &&
|
||||
requires(quantity_type q) { quantity_from_origin_is_an_implementation_detail_ += q; }
|
||||
friend constexpr decltype(auto) operator+=(QP&& qp, const quantity_type& q)
|
||||
template<typename FwdQP, std::derived_from<quantity_point> QP = std::remove_cvref_t<FwdQP>>
|
||||
requires requires(quantity_type q) { quantity_from_origin_is_an_implementation_detail_ += q; }
|
||||
friend constexpr decltype(auto) operator+=(FwdQP&& qp, const quantity_type& q)
|
||||
{
|
||||
qp.quantity_from_origin_is_an_implementation_detail_ += q;
|
||||
return std::forward<QP>(qp);
|
||||
return std::forward<FwdQP>(qp);
|
||||
}
|
||||
|
||||
template<typename QP>
|
||||
requires std::derived_from<std::remove_cvref_t<QP>, quantity_point> &&
|
||||
requires(quantity_type q) { quantity_from_origin_is_an_implementation_detail_ -= q; }
|
||||
friend constexpr decltype(auto) operator-=(QP&& qp, const quantity_type& q)
|
||||
template<typename FwdQP, std::derived_from<quantity_point> QP = std::remove_cvref_t<FwdQP>>
|
||||
requires requires(quantity_type q) { quantity_from_origin_is_an_implementation_detail_ -= q; }
|
||||
friend constexpr decltype(auto) operator-=(FwdQP&& qp, const quantity_type& q)
|
||||
{
|
||||
qp.quantity_from_origin_is_an_implementation_detail_ -= q;
|
||||
return std::forward<QP>(qp);
|
||||
return std::forward<FwdQP>(qp);
|
||||
}
|
||||
|
||||
// binary operators on quantity points
|
||||
|
||||
@@ -38,13 +38,13 @@ struct absolute_point_origin;
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_quantity_point = false;
|
||||
constexpr bool is_quantity_point = false;
|
||||
|
||||
template<auto Q>
|
||||
void to_base_specialization_of_absolute_point_origin(const volatile absolute_point_origin<Q>*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_absolute_point_origin =
|
||||
constexpr bool is_derived_from_specialization_of_absolute_point_origin =
|
||||
requires(T* type) { to_base_specialization_of_absolute_point_origin(type); };
|
||||
|
||||
} // namespace detail
|
||||
@@ -66,7 +66,7 @@ template<auto QP>
|
||||
void to_base_specialization_of_relative_point_origin(const volatile relative_point_origin<QP>*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_relative_point_origin =
|
||||
constexpr bool is_derived_from_specialization_of_relative_point_origin =
|
||||
requires(T* type) { to_base_specialization_of_relative_point_origin(type); };
|
||||
|
||||
struct point_origin_interface;
|
||||
@@ -99,12 +99,12 @@ template<auto R, auto PO, typename Rep>
|
||||
void to_base_specialization_of_quantity_point(const volatile quantity_point<R, PO, Rep>*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_quantity_point =
|
||||
constexpr bool is_derived_from_specialization_of_quantity_point =
|
||||
requires(T* type) { to_base_specialization_of_quantity_point(type); };
|
||||
|
||||
template<typename T>
|
||||
requires is_derived_from_specialization_of_quantity_point<T>
|
||||
inline constexpr bool is_quantity_point<T> = true;
|
||||
constexpr bool is_quantity_point<T> = true;
|
||||
|
||||
template<PointOrigin PO1, PointOrigin PO2>
|
||||
[[nodiscard]] consteval bool same_absolute_point_origins(PO1 po1, PO2 po2)
|
||||
|
||||
@@ -159,13 +159,11 @@ struct quantity_spec_interface : quantity_spec_interface_base {
|
||||
return make_reference(self, u);
|
||||
}
|
||||
|
||||
template<typename Self, typename Q>
|
||||
requires Quantity<std::remove_cvref_t<Q>> &&
|
||||
QuantitySpecExplicitlyConvertibleTo<std::remove_reference_t<Q>::quantity_spec, Self{}>
|
||||
[[nodiscard]] constexpr Quantity auto operator()(this Self self, Q&& q)
|
||||
template<typename Self, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
requires QuantitySpecExplicitlyConvertibleTo<Q::quantity_spec, Self{}>
|
||||
[[nodiscard]] constexpr Quantity auto operator()(this Self self, FwdQ&& q)
|
||||
{
|
||||
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
|
||||
make_reference(self, std::remove_cvref_t<Q>::unit)};
|
||||
return quantity{std::forward<FwdQ>(q).numerical_value_is_an_implementation_detail_, make_reference(self, Q::unit)};
|
||||
}
|
||||
#else
|
||||
template<typename Self_ = Self, UnitOf<Self_{}> U>
|
||||
@@ -174,13 +172,12 @@ struct quantity_spec_interface : quantity_spec_interface_base {
|
||||
return make_reference(Self{}, u);
|
||||
}
|
||||
|
||||
template<typename Q, typename Self_ = Self>
|
||||
requires Quantity<std::remove_cvref_t<Q>> &&
|
||||
QuantitySpecExplicitlyConvertibleTo<std::remove_reference_t<Q>::quantity_spec, Self_{}>
|
||||
[[nodiscard]] constexpr Quantity auto operator()(Q&& q) const
|
||||
template<typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>, typename Self_ = Self>
|
||||
requires QuantitySpecExplicitlyConvertibleTo<Q::quantity_spec, Self_{}>
|
||||
[[nodiscard]] constexpr Quantity auto operator()(FwdQ&& q) const
|
||||
{
|
||||
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
|
||||
make_reference(Self{}, std::remove_cvref_t<Q>::unit)};
|
||||
return quantity{std::forward<FwdQ>(q).numerical_value_is_an_implementation_detail_,
|
||||
make_reference(Self{}, Q::unit)};
|
||||
}
|
||||
#endif
|
||||
};
|
||||
@@ -371,13 +368,12 @@ struct quantity_spec<Self, QS, Args...> : detail::propagate_equation<QS>, detail
|
||||
return detail::make_reference(Self{}, u);
|
||||
}
|
||||
|
||||
template<typename Q, typename Self_ = Self>
|
||||
requires Quantity<std::remove_cvref_t<Q>> &&
|
||||
detail::QuantitySpecExplicitlyConvertibleTo<std::remove_reference_t<Q>::quantity_spec, Self_{}>
|
||||
[[nodiscard]] constexpr Quantity auto operator()(Q&& q) const
|
||||
template<typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>, typename Self_ = Self>
|
||||
requires detail::QuantitySpecExplicitlyConvertibleTo<Q::quantity_spec, Self_{}>
|
||||
[[nodiscard]] constexpr Quantity auto operator()(FwdQ&& q) const
|
||||
{
|
||||
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
|
||||
detail::make_reference(Self{}, std::remove_cvref_t<Q>::unit)};
|
||||
return quantity{std::forward<FwdQ>(q).numerical_value_is_an_implementation_detail_,
|
||||
detail::make_reference(Self{}, Q::unit)};
|
||||
}
|
||||
#endif
|
||||
};
|
||||
@@ -556,7 +552,7 @@ struct kind_of_<Q> final : quantity_spec<kind_of_<Q>, Q{}>::_base_type_ {
|
||||
|
||||
MP_UNITS_EXPORT template<detail::QuantitySpecWithNoSpecifiers auto Q>
|
||||
requires detail::SameQuantitySpec<detail::get_kind_tree_root(Q), Q>
|
||||
inline constexpr kind_of_<MP_UNITS_REMOVE_CONST(decltype(Q))> kind_of;
|
||||
constexpr kind_of_<MP_UNITS_REMOVE_CONST(decltype(Q))> kind_of;
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
@@ -53,10 +53,10 @@ struct kind_of_;
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_kind_of = false;
|
||||
constexpr bool is_specialization_of_kind_of = false;
|
||||
|
||||
template<typename Q>
|
||||
inline constexpr bool is_specialization_of_kind_of<kind_of_<Q>> = true;
|
||||
constexpr bool is_specialization_of_kind_of<kind_of_<Q>> = true;
|
||||
|
||||
template<typename T>
|
||||
concept QuantityKindSpec = is_specialization_of_kind_of<T>;
|
||||
@@ -70,7 +70,7 @@ void to_base_specialization_of_quantity_spec(const volatile quantity_spec<T, Arg
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_quantity_spec =
|
||||
constexpr bool is_derived_from_specialization_of_quantity_spec =
|
||||
requires(T* type) { to_base_specialization_of_quantity_spec(type); };
|
||||
|
||||
/**
|
||||
@@ -86,16 +86,16 @@ template<typename T>
|
||||
struct is_dimensionless : std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_power_of_quantity_spec = requires {
|
||||
constexpr bool is_power_of_quantity_spec = requires {
|
||||
requires is_specialization_of_power<T> &&
|
||||
(NamedQuantitySpec<typename T::factor> || is_dimensionless<typename T::factor>::value);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_per_of_quantity_specs = false;
|
||||
constexpr bool is_per_of_quantity_specs = false;
|
||||
|
||||
template<typename... Ts>
|
||||
inline constexpr bool is_per_of_quantity_specs<per<Ts...>> =
|
||||
constexpr bool is_per_of_quantity_specs<per<Ts...>> =
|
||||
(... && (NamedQuantitySpec<Ts> || is_dimensionless<Ts>::value || is_power_of_quantity_spec<Ts>));
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -190,36 +190,36 @@ struct reference {
|
||||
};
|
||||
|
||||
|
||||
template<typename Rep, Reference R>
|
||||
requires(!detail::OffsetUnit<decltype(get_unit(R{}))>) &&
|
||||
RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
|
||||
[[nodiscard]] constexpr quantity<R{}, std::remove_cvref_t<Rep>> operator*(Rep&& lhs, R)
|
||||
template<typename FwdRep, Reference R,
|
||||
RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
|
||||
requires(!detail::OffsetUnit<decltype(get_unit(R{}))>)
|
||||
[[nodiscard]] constexpr quantity<R{}, Rep> operator*(FwdRep&& lhs, R)
|
||||
{
|
||||
return quantity{std::forward<Rep>(lhs), R{}};
|
||||
return quantity{std::forward<FwdRep>(lhs), R{}};
|
||||
}
|
||||
|
||||
template<typename Rep, Reference R>
|
||||
requires(!detail::OffsetUnit<decltype(get_unit(R{}))>) &&
|
||||
RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
|
||||
[[nodiscard]] constexpr quantity<inverse(R{}), std::remove_cvref_t<Rep>> operator/(Rep&& lhs, R)
|
||||
template<typename FwdRep, Reference R,
|
||||
RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
|
||||
requires(!detail::OffsetUnit<decltype(get_unit(R{}))>)
|
||||
[[nodiscard]] constexpr quantity<inverse(R{}), Rep> operator/(FwdRep&& lhs, R)
|
||||
{
|
||||
return quantity{std::forward<Rep>(lhs), inverse(R{})};
|
||||
return quantity{std::forward<FwdRep>(lhs), inverse(R{})};
|
||||
}
|
||||
|
||||
template<typename Rep, Reference R>
|
||||
requires detail::OffsetUnit<decltype(get_unit(R{}))> &&
|
||||
RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
|
||||
[[noreturn]] constexpr auto operator*(Rep&&, R)
|
||||
template<typename FwdRep, Reference R,
|
||||
RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
|
||||
requires detail::OffsetUnit<decltype(get_unit(R{}))>
|
||||
[[noreturn]] constexpr auto operator*(FwdRep&&, R)
|
||||
{
|
||||
static_assert(!detail::OffsetUnit<decltype(get_unit(R{}))>,
|
||||
"References using offset units (e.g., temperatures) may be constructed only with the `delta` or "
|
||||
"`absolute` helpers");
|
||||
}
|
||||
|
||||
template<typename Rep, Reference R>
|
||||
requires detail::OffsetUnit<decltype(get_unit(R{}))> &&
|
||||
RepresentationOf<std::remove_cvref_t<Rep>, get_quantity_spec(R{}).character>
|
||||
[[noreturn]] constexpr auto operator/(Rep&&, R)
|
||||
template<typename FwdRep, Reference R,
|
||||
RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
|
||||
requires detail::OffsetUnit<decltype(get_unit(R{}))>
|
||||
[[noreturn]] constexpr auto operator/(FwdRep&&, R)
|
||||
{
|
||||
static_assert(!detail::OffsetUnit<decltype(get_unit(R{}))>,
|
||||
"References using offset units (e.g., temperatures) may be constructed only with the `delta` or "
|
||||
@@ -246,20 +246,16 @@ constexpr auto operator/(R, Rep&&)
|
||||
= delete;
|
||||
#endif
|
||||
|
||||
template<typename Q, Reference R>
|
||||
requires Quantity<std::remove_cvref_t<Q>>
|
||||
[[nodiscard]] constexpr Quantity auto operator*(Q&& q, R)
|
||||
template<typename FwdQ, Reference R, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
[[nodiscard]] constexpr Quantity auto operator*(FwdQ&& q, R)
|
||||
{
|
||||
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
|
||||
std::remove_cvref_t<Q>::reference * R{}};
|
||||
return quantity{std::forward<FwdQ>(q).numerical_value_is_an_implementation_detail_, Q::reference * R{}};
|
||||
}
|
||||
|
||||
template<typename Q, Reference R>
|
||||
requires Quantity<std::remove_cvref_t<Q>>
|
||||
[[nodiscard]] constexpr Quantity auto operator/(Q&& q, R)
|
||||
template<typename FwdQ, Reference R, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
[[nodiscard]] constexpr Quantity auto operator/(FwdQ&& q, R)
|
||||
{
|
||||
return quantity{std::forward<Q>(q).numerical_value_is_an_implementation_detail_,
|
||||
std::remove_cvref_t<Q>::reference / R{}};
|
||||
return quantity{std::forward<FwdQ>(q).numerical_value_is_an_implementation_detail_, Q::reference / R{}};
|
||||
}
|
||||
|
||||
template<Reference R, typename Q>
|
||||
|
||||
@@ -79,10 +79,14 @@ concept Scalable =
|
||||
CastableNumber<T> || (requires { typename wrapped_type_t<T>; } && CastableNumber<wrapped_type_t<T>> &&
|
||||
ScalableNumber<T, std::common_type_t<wrapped_type_t<T>, std::intmax_t>>);
|
||||
|
||||
template<typename T>
|
||||
concept WeaklyRegular = std::copyable<T> && std::equality_comparable<T>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
MP_UNITS_EXPORT template<typename T>
|
||||
concept Representation = (is_scalar<T> || is_vector<T> || is_tensor<T>)&&std::regular<T> && detail::Scalable<T>;
|
||||
concept Representation =
|
||||
(is_scalar<T> || is_vector<T> || is_tensor<T>)&&detail::WeaklyRegular<T> && detail::Scalable<T>;
|
||||
|
||||
MP_UNITS_EXPORT template<typename T, quantity_character Ch>
|
||||
concept RepresentationOf = Representation<T> && ((Ch == quantity_character::scalar && is_scalar<T>) ||
|
||||
|
||||
@@ -64,7 +64,7 @@ template<Magnitude auto M, Unit U>
|
||||
struct scaled_unit_impl;
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_scaled_unit = false;
|
||||
constexpr bool is_specialization_of_scaled_unit = false;
|
||||
|
||||
template<DerivedUnitExpr... Expr>
|
||||
struct derived_unit_impl;
|
||||
@@ -241,7 +241,7 @@ struct scaled_unit final : detail::scaled_unit_impl<M, U> {};
|
||||
namespace detail {
|
||||
|
||||
template<auto M, Unit U>
|
||||
inline constexpr bool is_specialization_of_scaled_unit<scaled_unit<M, U>> = true;
|
||||
constexpr bool is_specialization_of_scaled_unit<scaled_unit<M, U>> = true;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -386,7 +386,7 @@ struct named_unit<Symbol, U, QS, PO> : decltype(U)::_base_type_ {
|
||||
* struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U> {};
|
||||
*
|
||||
* template<PrefixableUnit auto U>
|
||||
* inline constexpr kilo_<U> kilo;
|
||||
* constexpr kilo_<U> kilo;
|
||||
*
|
||||
* inline constexpr auto kilogram = si::kilo<gram>;
|
||||
* @endcode
|
||||
@@ -534,10 +534,10 @@ template<Unit T, typename... Expr>
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_specialization_of_derived_unit = false;
|
||||
constexpr bool is_specialization_of_derived_unit = false;
|
||||
|
||||
template<typename... Expr>
|
||||
inline constexpr bool is_specialization_of_derived_unit<derived_unit<Expr...>> = true;
|
||||
constexpr bool is_specialization_of_derived_unit<derived_unit<Expr...>> = true;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -675,14 +675,14 @@ template<Unit U1, Unit U2>
|
||||
* be provided.
|
||||
*/
|
||||
template<Unit auto U>
|
||||
inline constexpr bool space_before_unit_symbol = true;
|
||||
constexpr bool space_before_unit_symbol = true;
|
||||
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<one> = false;
|
||||
MP_UNITS_INLINE constexpr bool space_before_unit_symbol<one> = false;
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<percent> = false;
|
||||
MP_UNITS_INLINE constexpr bool space_before_unit_symbol<percent> = false;
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<per_mille> = false;
|
||||
MP_UNITS_INLINE constexpr bool space_before_unit_symbol<per_mille> = false;
|
||||
|
||||
// get_unit_symbol
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ template<symbol_text Symbol, auto... Args>
|
||||
void to_base_specialization_of_named_unit(const volatile named_unit<Symbol, Args...>*);
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_derived_from_specialization_of_named_unit =
|
||||
constexpr bool is_derived_from_specialization_of_named_unit =
|
||||
requires(T* t) { to_base_specialization_of_named_unit(t); };
|
||||
|
||||
} // namespace detail
|
||||
@@ -73,14 +73,13 @@ concept PrefixableUnit = Unit<T> && detail::is_derived_from_specialization_of_na
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_power_of_unit =
|
||||
requires { requires is_specialization_of_power<T> && Unit<typename T::factor>; };
|
||||
constexpr bool is_power_of_unit = requires { requires is_specialization_of_power<T> && Unit<typename T::factor>; };
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_per_of_units = false;
|
||||
constexpr bool is_per_of_units = false;
|
||||
|
||||
template<typename... Ts>
|
||||
inline constexpr bool is_per_of_units<per<Ts...>> = (... && (Unit<Ts> || is_power_of_unit<Ts>));
|
||||
constexpr bool is_per_of_units<per<Ts...>> = (... && (Unit<Ts> || is_power_of_unit<Ts>));
|
||||
|
||||
template<typename T>
|
||||
concept DerivedUnitExpr = Unit<T> || detail::is_power_of_unit<T> || detail::is_per_of_units<T>;
|
||||
|
||||
@@ -44,13 +44,12 @@ namespace mp_units {
|
||||
*
|
||||
* @tparam ToU a unit to use for a target quantity
|
||||
*/
|
||||
template<Unit auto ToU, typename Q>
|
||||
requires Quantity<std::remove_cvref_t<Q>> && (convertible(std::remove_reference_t<Q>::reference, ToU))
|
||||
[[nodiscard]] constexpr Quantity auto value_cast(Q&& q)
|
||||
template<Unit auto ToU, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
requires(convertible(Q::reference, ToU))
|
||||
[[nodiscard]] constexpr Quantity auto value_cast(FwdQ&& q)
|
||||
{
|
||||
using q_type = std::remove_reference_t<Q>;
|
||||
return detail::sudo_cast<quantity<detail::make_reference(q_type::quantity_spec, ToU), typename q_type::rep>>(
|
||||
std::forward<Q>(q));
|
||||
return detail::sudo_cast<quantity<detail::make_reference(Q::quantity_spec, ToU), typename Q::rep>>(
|
||||
std::forward<FwdQ>(q));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,13 +62,11 @@ template<Unit auto ToU, typename Q>
|
||||
*
|
||||
* @tparam ToRep a representation type to use for a target quantity
|
||||
*/
|
||||
template<Representation ToRep, typename Q>
|
||||
requires Quantity<std::remove_cvref_t<Q>> &&
|
||||
RepresentationOf<ToRep, std::remove_reference_t<Q>::quantity_spec.character> &&
|
||||
std::constructible_from<ToRep, typename std::remove_reference_t<Q>::rep>
|
||||
[[nodiscard]] constexpr quantity<std::remove_reference_t<Q>::reference, ToRep> value_cast(Q&& q)
|
||||
template<Representation ToRep, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
requires RepresentationOf<ToRep, Q::quantity_spec.character> && std::constructible_from<ToRep, typename Q::rep>
|
||||
[[nodiscard]] constexpr quantity<Q::reference, ToRep> value_cast(FwdQ&& q)
|
||||
{
|
||||
return detail::sudo_cast<quantity<std::remove_reference_t<Q>::reference, ToRep>>(std::forward<Q>(q));
|
||||
return detail::sudo_cast<quantity<Q::reference, ToRep>>(std::forward<FwdQ>(q));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,14 +80,12 @@ template<Representation ToRep, typename Q>
|
||||
* @tparam ToU a unit to use for the target quantity
|
||||
* @tparam ToRep a representation type to use for the target quantity
|
||||
*/
|
||||
template<Unit auto ToU, Representation ToRep, typename Q>
|
||||
requires Quantity<std::remove_cvref_t<Q>> && (convertible(std::remove_reference_t<Q>::reference, ToU)) &&
|
||||
RepresentationOf<ToRep, std::remove_reference_t<Q>::quantity_spec.character> &&
|
||||
std::constructible_from<ToRep, typename std::remove_reference_t<Q>::rep>
|
||||
[[nodiscard]] constexpr Quantity auto value_cast(Q&& q)
|
||||
template<Unit auto ToU, Representation ToRep, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
requires(convertible(Q::reference, ToU)) && RepresentationOf<ToRep, Q::quantity_spec.character> &&
|
||||
std::constructible_from<ToRep, typename Q::rep>
|
||||
[[nodiscard]] constexpr Quantity auto value_cast(FwdQ&& q)
|
||||
{
|
||||
using q_type = std::remove_reference_t<Q>;
|
||||
return detail::sudo_cast<quantity<detail::make_reference(q_type::quantity_spec, ToU), ToRep>>(std::forward<Q>(q));
|
||||
return detail::sudo_cast<quantity<detail::make_reference(Q::quantity_spec, ToU), ToRep>>(std::forward<FwdQ>(q));
|
||||
}
|
||||
|
||||
|
||||
@@ -108,13 +103,12 @@ template<Unit auto ToU, Representation ToRep, typename Q>
|
||||
*
|
||||
* @tparam ToQ a target quantity type to which to cast the representation
|
||||
*/
|
||||
template<Quantity ToQ, typename Q>
|
||||
requires Quantity<std::remove_cvref_t<Q>> && (convertible(std::remove_reference_t<Q>::reference, ToQ::unit)) &&
|
||||
(ToQ::quantity_spec == std::remove_reference_t<Q>::quantity_spec) &&
|
||||
std::constructible_from<typename ToQ::rep, typename std::remove_reference_t<Q>::rep>
|
||||
[[nodiscard]] constexpr Quantity auto value_cast(Q&& q)
|
||||
template<Quantity ToQ, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
|
||||
requires(convertible(Q::reference, ToQ::unit)) &&
|
||||
(ToQ::quantity_spec == Q::quantity_spec) && std::constructible_from<typename ToQ::rep, typename Q::rep>
|
||||
[[nodiscard]] constexpr Quantity auto value_cast(FwdQ&& q)
|
||||
{
|
||||
return detail::sudo_cast<ToQ>(std::forward<Q>(q));
|
||||
return detail::sudo_cast<ToQ>(std::forward<FwdQ>(q));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,12 +121,12 @@ template<Quantity ToQ, typename Q>
|
||||
*
|
||||
* @tparam ToU a unit to use for a target quantity point
|
||||
*/
|
||||
template<Unit auto ToU, typename QP>
|
||||
requires QuantityPoint<std::remove_cvref_t<QP>> && (convertible(std::remove_reference_t<QP>::reference, ToU))
|
||||
[[nodiscard]] constexpr QuantityPoint auto value_cast(QP&& qp)
|
||||
template<Unit auto ToU, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
requires(convertible(QP::reference, ToU))
|
||||
[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp)
|
||||
{
|
||||
return quantity_point{value_cast<ToU>(std::forward<QP>(qp).quantity_from_origin_is_an_implementation_detail_),
|
||||
std::remove_reference_t<QP>::point_origin};
|
||||
return quantity_point{value_cast<ToU>(std::forward<FwdQP>(qp).quantity_from_origin_is_an_implementation_detail_),
|
||||
QP::point_origin};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,16 +139,12 @@ template<Unit auto ToU, typename QP>
|
||||
*
|
||||
* @tparam ToRep a representation type to use for a target quantity point
|
||||
*/
|
||||
template<Representation ToRep, typename QP>
|
||||
requires QuantityPoint<std::remove_cvref_t<QP>> &&
|
||||
RepresentationOf<ToRep, std::remove_reference_t<QP>::quantity_spec.character> &&
|
||||
std::constructible_from<ToRep, typename std::remove_reference_t<QP>::rep>
|
||||
[[nodiscard]] constexpr quantity_point<std::remove_reference_t<QP>::reference,
|
||||
std::remove_reference_t<QP>::point_origin, ToRep>
|
||||
value_cast(QP&& qp)
|
||||
template<Representation ToRep, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
requires RepresentationOf<ToRep, QP::quantity_spec.character> && std::constructible_from<ToRep, typename QP::rep>
|
||||
[[nodiscard]] constexpr quantity_point<QP::reference, QP::point_origin, ToRep> value_cast(FwdQP&& qp)
|
||||
{
|
||||
return {value_cast<ToRep>(std::forward<QP>(qp).quantity_from_origin_is_an_implementation_detail_),
|
||||
std::remove_reference_t<QP>::point_origin};
|
||||
return {value_cast<ToRep>(std::forward<FwdQP>(qp).quantity_from_origin_is_an_implementation_detail_),
|
||||
QP::point_origin};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,14 +158,14 @@ value_cast(QP&& qp)
|
||||
* @tparam ToU a unit to use for the target quantity
|
||||
* @tparam ToRep a representation type to use for the target quantity
|
||||
*/
|
||||
template<Unit auto ToU, Representation ToRep, typename QP>
|
||||
requires QuantityPoint<std::remove_cvref_t<QP>> && (convertible(std::remove_reference_t<QP>::reference, ToU)) &&
|
||||
RepresentationOf<ToRep, std::remove_reference_t<QP>::quantity_spec.character> &&
|
||||
std::constructible_from<ToRep, typename std::remove_reference_t<QP>::rep>
|
||||
[[nodiscard]] constexpr QuantityPoint auto value_cast(QP&& qp)
|
||||
template<Unit auto ToU, Representation ToRep, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
requires(convertible(QP::reference, ToU)) && RepresentationOf<ToRep, QP::quantity_spec.character> &&
|
||||
std::constructible_from<ToRep, typename QP::rep>
|
||||
[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp)
|
||||
{
|
||||
return quantity_point{value_cast<ToU, ToRep>(std::forward<QP>(qp).quantity_from_origin_is_an_implementation_detail_),
|
||||
std::remove_reference_t<QP>::point_origin};
|
||||
return quantity_point{
|
||||
value_cast<ToU, ToRep>(std::forward<FwdQP>(qp).quantity_from_origin_is_an_implementation_detail_),
|
||||
QP::point_origin};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,14 +184,13 @@ template<Unit auto ToU, Representation ToRep, typename QP>
|
||||
*
|
||||
* @tparam ToQ a target quantity type to which to cast the representation of the point
|
||||
*/
|
||||
template<Quantity ToQ, typename QP>
|
||||
requires QuantityPoint<std::remove_cvref_t<QP>> && (convertible(std::remove_reference_t<QP>::reference, ToQ::unit)) &&
|
||||
(ToQ::quantity_spec == std::remove_reference_t<QP>::quantity_spec) &&
|
||||
std::constructible_from<typename ToQ::rep, typename std::remove_reference_t<QP>::rep>
|
||||
[[nodiscard]] constexpr QuantityPoint auto value_cast(QP&& qp)
|
||||
template<Quantity ToQ, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
requires(convertible(QP::reference, ToQ::unit)) &&
|
||||
(ToQ::quantity_spec == QP::quantity_spec) && std::constructible_from<typename ToQ::rep, typename QP::rep>
|
||||
[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp)
|
||||
{
|
||||
return quantity_point{value_cast<ToQ>(std::forward<QP>(qp).quantity_from_origin_is_an_implementation_detail_),
|
||||
std::remove_reference_t<QP>::point_origin};
|
||||
return quantity_point{value_cast<ToQ>(std::forward<FwdQP>(qp).quantity_from_origin_is_an_implementation_detail_),
|
||||
QP::point_origin};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,16 +221,13 @@ template<Quantity ToQ, typename QP>
|
||||
*
|
||||
* @tparam ToQP a target quantity point type to which to cast the representation of the point
|
||||
*/
|
||||
template<QuantityPoint ToQP, typename QP>
|
||||
requires QuantityPoint<std::remove_cvref_t<QP>> &&
|
||||
(convertible(std::remove_reference_t<QP>::reference, ToQP::unit)) &&
|
||||
(ToQP::quantity_spec == std::remove_reference_t<QP>::quantity_spec) &&
|
||||
(detail::same_absolute_point_origins(ToQP::point_origin, std::remove_reference_t<QP>::point_origin)) &&
|
||||
std::constructible_from<typename ToQP::rep, typename std::remove_reference_t<QP>::rep>
|
||||
[[nodiscard]] constexpr QuantityPoint auto value_cast(QP&& qp)
|
||||
template<QuantityPoint ToQP, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
|
||||
requires(convertible(QP::reference, ToQP::unit)) && (ToQP::quantity_spec == QP::quantity_spec) &&
|
||||
(detail::same_absolute_point_origins(ToQP::point_origin, QP::point_origin)) &&
|
||||
std::constructible_from<typename ToQP::rep, typename QP::rep>
|
||||
[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp)
|
||||
{
|
||||
return detail::sudo_cast<ToQP>(std::forward<QP>(qp));
|
||||
return detail::sudo_cast<ToQP>(std::forward<FwdQP>(qp));
|
||||
}
|
||||
|
||||
|
||||
} // namespace mp_units
|
||||
@@ -62,8 +62,8 @@ inline constexpr auto deg2 = square(degree);
|
||||
} // namespace angular
|
||||
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<angular::degree> = false;
|
||||
MP_UNITS_INLINE constexpr bool space_before_unit_symbol<angular::degree> = false;
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<angular::gradian> = false;
|
||||
MP_UNITS_INLINE constexpr bool space_before_unit_symbol<angular::gradian> = false;
|
||||
|
||||
} // namespace mp_units
|
||||
@@ -36,7 +36,7 @@ MP_UNITS_EXPORT
|
||||
namespace mp_units {
|
||||
|
||||
template<>
|
||||
inline constexpr std::optional<std::intmax_t> known_first_factor<334'524'384'739> = 334'524'384'739;
|
||||
constexpr std::optional<std::intmax_t> known_first_factor<334'524'384'739> = 334'524'384'739;
|
||||
|
||||
namespace hep {
|
||||
|
||||
|
||||
@@ -42,14 +42,14 @@ template<PrefixableUnit U> struct yobi_ final : prefixed_unit<"Yi", mag_power<2,
|
||||
|
||||
MP_UNITS_EXPORT_BEGIN
|
||||
|
||||
template<PrefixableUnit auto U> inline constexpr kibi_<MP_UNITS_REMOVE_CONST(decltype(U))> kibi;
|
||||
template<PrefixableUnit auto U> inline constexpr mebi_<MP_UNITS_REMOVE_CONST(decltype(U))> mebi;
|
||||
template<PrefixableUnit auto U> inline constexpr gibi_<MP_UNITS_REMOVE_CONST(decltype(U))> gibi;
|
||||
template<PrefixableUnit auto U> inline constexpr tebi_<MP_UNITS_REMOVE_CONST(decltype(U))> tebi;
|
||||
template<PrefixableUnit auto U> inline constexpr pebi_<MP_UNITS_REMOVE_CONST(decltype(U))> pebi;
|
||||
template<PrefixableUnit auto U> inline constexpr exbi_<MP_UNITS_REMOVE_CONST(decltype(U))> exbi;
|
||||
template<PrefixableUnit auto U> inline constexpr zebi_<MP_UNITS_REMOVE_CONST(decltype(U))> zebi;
|
||||
template<PrefixableUnit auto U> inline constexpr yobi_<MP_UNITS_REMOVE_CONST(decltype(U))> yobi;
|
||||
template<PrefixableUnit auto U> constexpr kibi_<MP_UNITS_REMOVE_CONST(decltype(U))> kibi;
|
||||
template<PrefixableUnit auto U> constexpr mebi_<MP_UNITS_REMOVE_CONST(decltype(U))> mebi;
|
||||
template<PrefixableUnit auto U> constexpr gibi_<MP_UNITS_REMOVE_CONST(decltype(U))> gibi;
|
||||
template<PrefixableUnit auto U> constexpr tebi_<MP_UNITS_REMOVE_CONST(decltype(U))> tebi;
|
||||
template<PrefixableUnit auto U> constexpr pebi_<MP_UNITS_REMOVE_CONST(decltype(U))> pebi;
|
||||
template<PrefixableUnit auto U> constexpr exbi_<MP_UNITS_REMOVE_CONST(decltype(U))> exbi;
|
||||
template<PrefixableUnit auto U> constexpr zebi_<MP_UNITS_REMOVE_CONST(decltype(U))> zebi;
|
||||
template<PrefixableUnit auto U> constexpr yobi_<MP_UNITS_REMOVE_CONST(decltype(U))> yobi;
|
||||
// clang-format on
|
||||
|
||||
MP_UNITS_EXPORT_END
|
||||
|
||||
@@ -93,7 +93,7 @@ struct chrono_point_origin_ final : absolute_point_origin<isq::time> {
|
||||
using clock = C;
|
||||
};
|
||||
MP_UNITS_EXPORT template<typename C>
|
||||
inline constexpr chrono_point_origin_<C> chrono_point_origin;
|
||||
constexpr chrono_point_origin_<C> chrono_point_origin;
|
||||
|
||||
MP_UNITS_EXPORT_BEGIN
|
||||
|
||||
|
||||
@@ -58,30 +58,30 @@ template<PrefixableUnit U> struct quetta_ final : prefixed_unit<"Q", mag_power<1
|
||||
|
||||
MP_UNITS_EXPORT_BEGIN
|
||||
|
||||
template<PrefixableUnit auto U> inline constexpr quecto_<MP_UNITS_REMOVE_CONST(decltype(U))> quecto;
|
||||
template<PrefixableUnit auto U> inline constexpr ronto_<MP_UNITS_REMOVE_CONST(decltype(U))> ronto;
|
||||
template<PrefixableUnit auto U> inline constexpr yocto_<MP_UNITS_REMOVE_CONST(decltype(U))> yocto;
|
||||
template<PrefixableUnit auto U> inline constexpr zepto_<MP_UNITS_REMOVE_CONST(decltype(U))> zepto;
|
||||
template<PrefixableUnit auto U> inline constexpr atto_<MP_UNITS_REMOVE_CONST(decltype(U))> atto;
|
||||
template<PrefixableUnit auto U> inline constexpr femto_<MP_UNITS_REMOVE_CONST(decltype(U))> femto;
|
||||
template<PrefixableUnit auto U> inline constexpr pico_<MP_UNITS_REMOVE_CONST(decltype(U))> pico;
|
||||
template<PrefixableUnit auto U> inline constexpr nano_<MP_UNITS_REMOVE_CONST(decltype(U))> nano;
|
||||
template<PrefixableUnit auto U> inline constexpr micro_<MP_UNITS_REMOVE_CONST(decltype(U))> micro;
|
||||
template<PrefixableUnit auto U> inline constexpr milli_<MP_UNITS_REMOVE_CONST(decltype(U))> milli;
|
||||
template<PrefixableUnit auto U> inline constexpr centi_<MP_UNITS_REMOVE_CONST(decltype(U))> centi;
|
||||
template<PrefixableUnit auto U> inline constexpr deci_<MP_UNITS_REMOVE_CONST(decltype(U))> deci;
|
||||
template<PrefixableUnit auto U> inline constexpr deca_<MP_UNITS_REMOVE_CONST(decltype(U))> deca;
|
||||
template<PrefixableUnit auto U> inline constexpr hecto_<MP_UNITS_REMOVE_CONST(decltype(U))> hecto;
|
||||
template<PrefixableUnit auto U> inline constexpr kilo_<MP_UNITS_REMOVE_CONST(decltype(U))> kilo;
|
||||
template<PrefixableUnit auto U> inline constexpr mega_<MP_UNITS_REMOVE_CONST(decltype(U))> mega;
|
||||
template<PrefixableUnit auto U> inline constexpr giga_<MP_UNITS_REMOVE_CONST(decltype(U))> giga;
|
||||
template<PrefixableUnit auto U> inline constexpr tera_<MP_UNITS_REMOVE_CONST(decltype(U))> tera;
|
||||
template<PrefixableUnit auto U> inline constexpr peta_<MP_UNITS_REMOVE_CONST(decltype(U))> peta;
|
||||
template<PrefixableUnit auto U> inline constexpr exa_<MP_UNITS_REMOVE_CONST(decltype(U))> exa;
|
||||
template<PrefixableUnit auto U> inline constexpr zetta_<MP_UNITS_REMOVE_CONST(decltype(U))> zetta;
|
||||
template<PrefixableUnit auto U> inline constexpr yotta_<MP_UNITS_REMOVE_CONST(decltype(U))> yotta;
|
||||
template<PrefixableUnit auto U> inline constexpr ronna_<MP_UNITS_REMOVE_CONST(decltype(U))> ronna;
|
||||
template<PrefixableUnit auto U> inline constexpr quetta_<MP_UNITS_REMOVE_CONST(decltype(U))> quetta;
|
||||
template<PrefixableUnit auto U> constexpr quecto_<MP_UNITS_REMOVE_CONST(decltype(U))> quecto;
|
||||
template<PrefixableUnit auto U> constexpr ronto_<MP_UNITS_REMOVE_CONST(decltype(U))> ronto;
|
||||
template<PrefixableUnit auto U> constexpr yocto_<MP_UNITS_REMOVE_CONST(decltype(U))> yocto;
|
||||
template<PrefixableUnit auto U> constexpr zepto_<MP_UNITS_REMOVE_CONST(decltype(U))> zepto;
|
||||
template<PrefixableUnit auto U> constexpr atto_<MP_UNITS_REMOVE_CONST(decltype(U))> atto;
|
||||
template<PrefixableUnit auto U> constexpr femto_<MP_UNITS_REMOVE_CONST(decltype(U))> femto;
|
||||
template<PrefixableUnit auto U> constexpr pico_<MP_UNITS_REMOVE_CONST(decltype(U))> pico;
|
||||
template<PrefixableUnit auto U> constexpr nano_<MP_UNITS_REMOVE_CONST(decltype(U))> nano;
|
||||
template<PrefixableUnit auto U> constexpr micro_<MP_UNITS_REMOVE_CONST(decltype(U))> micro;
|
||||
template<PrefixableUnit auto U> constexpr milli_<MP_UNITS_REMOVE_CONST(decltype(U))> milli;
|
||||
template<PrefixableUnit auto U> constexpr centi_<MP_UNITS_REMOVE_CONST(decltype(U))> centi;
|
||||
template<PrefixableUnit auto U> constexpr deci_<MP_UNITS_REMOVE_CONST(decltype(U))> deci;
|
||||
template<PrefixableUnit auto U> constexpr deca_<MP_UNITS_REMOVE_CONST(decltype(U))> deca;
|
||||
template<PrefixableUnit auto U> constexpr hecto_<MP_UNITS_REMOVE_CONST(decltype(U))> hecto;
|
||||
template<PrefixableUnit auto U> constexpr kilo_<MP_UNITS_REMOVE_CONST(decltype(U))> kilo;
|
||||
template<PrefixableUnit auto U> constexpr mega_<MP_UNITS_REMOVE_CONST(decltype(U))> mega;
|
||||
template<PrefixableUnit auto U> constexpr giga_<MP_UNITS_REMOVE_CONST(decltype(U))> giga;
|
||||
template<PrefixableUnit auto U> constexpr tera_<MP_UNITS_REMOVE_CONST(decltype(U))> tera;
|
||||
template<PrefixableUnit auto U> constexpr peta_<MP_UNITS_REMOVE_CONST(decltype(U))> peta;
|
||||
template<PrefixableUnit auto U> constexpr exa_<MP_UNITS_REMOVE_CONST(decltype(U))> exa;
|
||||
template<PrefixableUnit auto U> constexpr zetta_<MP_UNITS_REMOVE_CONST(decltype(U))> zetta;
|
||||
template<PrefixableUnit auto U> constexpr yotta_<MP_UNITS_REMOVE_CONST(decltype(U))> yotta;
|
||||
template<PrefixableUnit auto U> constexpr ronna_<MP_UNITS_REMOVE_CONST(decltype(U))> ronna;
|
||||
template<PrefixableUnit auto U> constexpr quetta_<MP_UNITS_REMOVE_CONST(decltype(U))> quetta;
|
||||
// clang-format on
|
||||
|
||||
MP_UNITS_EXPORT_END
|
||||
|
||||
@@ -126,10 +126,10 @@ using namespace non_si;
|
||||
} // namespace si
|
||||
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<non_si::degree> = false;
|
||||
MP_UNITS_INLINE constexpr bool space_before_unit_symbol<non_si::degree> = false;
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<non_si::arcminute> = false;
|
||||
MP_UNITS_INLINE constexpr bool space_before_unit_symbol<non_si::arcminute> = false;
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<non_si::arcsecond> = false;
|
||||
MP_UNITS_INLINE constexpr bool space_before_unit_symbol<non_si::arcsecond> = false;
|
||||
|
||||
} // namespace mp_units
|
||||
Reference in new issue
Block a user