Merge remote-tracking branch 'mpusz/master' into master-msvc-194

This commit is contained in:
Jonas Hoppe committed 2024-09-09 12:05:19 +02:00
commit 1d0dbf48b1
78 files changed
+1750 -1017

No files matched your search

+1 -1
View File
@@ -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.
+4
View File
@@ -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>
+83 -65
View File
@@ -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));
}
}
}
+11 -11
View File
@@ -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", "-");
+3 -3
View File
@@ -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>
+7 -8
View File
@@ -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 {
+17 -17
View File
@@ -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 {
+69 -73
View File
@@ -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>
+24 -28
View File
@@ -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>) ||
+9 -9
View File
@@ -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
+1 -1
View File
@@ -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