forked from mpusz/mp-units
Merge pull request #607 from czjhoppe/master-msvc-194-only-lib
[msvc] changes to make library compatible with msvc compiler (194)
This commit is contained in:
@@ -94,7 +94,7 @@ class MPUnitsConan(ConanFile):
|
|||||||
"gcc": "12",
|
"gcc": "12",
|
||||||
"clang": "16",
|
"clang": "16",
|
||||||
"apple-clang": "15",
|
"apple-clang": "15",
|
||||||
"msvc": "",
|
"msvc": "194",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"std_format": {
|
"std_format": {
|
||||||
|
@@ -151,7 +151,7 @@ void example()
|
|||||||
const auto acceleration = isq::acceleration(measurement{9.8, 0.1} * m / s2);
|
const auto acceleration = isq::acceleration(measurement{9.8, 0.1} * m / s2);
|
||||||
const auto time = measurement{1.2, 0.1} * s;
|
const auto time = measurement{1.2, 0.1} * s;
|
||||||
|
|
||||||
const MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(QuantityOf<isq::velocity>) auto velocity = acceleration * time;
|
const QuantityOf<isq::velocity> auto velocity = acceleration * time;
|
||||||
std::cout << acceleration << " * " << time << " = " << velocity << " = " << velocity.in(km / h) << '\n';
|
std::cout << acceleration << " * " << time << " = " << velocity << " = " << velocity.in(km / h) << '\n';
|
||||||
|
|
||||||
const auto length = measurement{123., 1.} * m;
|
const auto length = measurement{123., 1.} * m;
|
||||||
|
@@ -189,6 +189,8 @@ constexpr void handle_dynamic_spec(int& value, fmt_arg_ref<typename Context::cha
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MP_UNITS_DIAGNOSTIC_PUSH
|
||||||
|
MP_UNITS_DIAGNOSTIC_IGNORE_UNREACHABLE
|
||||||
struct width_checker {
|
struct width_checker {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] constexpr unsigned long long operator()(T value) const
|
[[nodiscard]] constexpr unsigned long long operator()(T value) const
|
||||||
@@ -199,9 +201,9 @@ struct width_checker {
|
|||||||
return static_cast<unsigned long long>(value);
|
return static_cast<unsigned long long>(value);
|
||||||
}
|
}
|
||||||
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("width is not integer"));
|
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("width is not integer"));
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
MP_UNITS_DIAGNOSTIC_POP
|
||||||
|
|
||||||
MP_UNITS_EXPORT_END
|
MP_UNITS_EXPORT_END
|
||||||
|
|
||||||
@@ -253,7 +255,6 @@ template<typename Char, typename Handler>
|
|||||||
if (c == '%') return begin; // mp-units extension
|
if (c == '%') return begin; // mp-units extension
|
||||||
if (!::mp_units::detail::is_name_start(c)) {
|
if (!::mp_units::detail::is_name_start(c)) {
|
||||||
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("invalid format string"));
|
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("invalid format string"));
|
||||||
return begin;
|
|
||||||
}
|
}
|
||||||
auto it = begin;
|
auto it = begin;
|
||||||
do {
|
do {
|
||||||
@@ -372,7 +373,6 @@ template<typename Char, typename Specs>
|
|||||||
if (c == '}') return begin;
|
if (c == '}') return begin;
|
||||||
if (c == '{') {
|
if (c == '{') {
|
||||||
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("invalid fill character '{'"));
|
MP_UNITS_THROW(MP_UNITS_STD_FMT::format_error("invalid fill character '{'"));
|
||||||
return begin;
|
|
||||||
}
|
}
|
||||||
specs.fill = {begin, to_unsigned(p - begin)};
|
specs.fill = {begin, to_unsigned(p - begin)};
|
||||||
begin = p + 1;
|
begin = p + 1;
|
||||||
|
@@ -76,9 +76,9 @@ template<AssociatedUnit U>
|
|||||||
template<AssociatedUnit U>
|
template<AssociatedUnit U>
|
||||||
[[nodiscard]] consteval auto get_associated_quantity(U u)
|
[[nodiscard]] consteval auto get_associated_quantity(U u)
|
||||||
{
|
{
|
||||||
constexpr bool all_kinds = all_are_kinds(u);
|
constexpr bool all_kinds = all_are_kinds(U{});
|
||||||
if constexpr (all_kinds)
|
if constexpr (all_kinds)
|
||||||
return kind_of<get_associated_quantity_impl(u)>;
|
return kind_of<get_associated_quantity_impl(U{})>;
|
||||||
else
|
else
|
||||||
return get_associated_quantity_impl(u);
|
return get_associated_quantity_impl(u);
|
||||||
}
|
}
|
||||||
|
@@ -80,16 +80,6 @@
|
|||||||
// workarounds for https://cplusplus.github.io/CWG/issues/2387.html
|
// workarounds for https://cplusplus.github.io/CWG/issues/2387.html
|
||||||
#define MP_UNITS_INLINE inline
|
#define MP_UNITS_INLINE inline
|
||||||
|
|
||||||
#if MP_UNITS_COMP_MSVC
|
|
||||||
|
|
||||||
#define MP_UNITS_TYPENAME typename
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define MP_UNITS_TYPENAME
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MP_UNITS_COMP_GCC
|
#if MP_UNITS_COMP_GCC
|
||||||
|
|
||||||
#define MP_UNITS_REMOVE_CONST(expr) std::remove_const_t<expr>
|
#define MP_UNITS_REMOVE_CONST(expr) std::remove_const_t<expr>
|
||||||
@@ -125,13 +115,15 @@ inline constexpr from_range_t from_range{};
|
|||||||
|
|
||||||
#if MP_UNITS_COMP_MSVC
|
#if MP_UNITS_COMP_MSVC
|
||||||
|
|
||||||
#define MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(X)
|
|
||||||
#define MP_UNITS_CONSTRAINED_NTTP_WORKAROUND(X)
|
#define MP_UNITS_CONSTRAINED_NTTP_WORKAROUND(X)
|
||||||
|
#define MP_UNITS_EXPRESSION_WORKAROUND(x) (x)
|
||||||
|
#define MP_UNITS_IS_VALUE_WORKAROUND(x) (x)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(X) X
|
|
||||||
#define MP_UNITS_CONSTRAINED_NTTP_WORKAROUND(X) X
|
#define MP_UNITS_CONSTRAINED_NTTP_WORKAROUND(X) X
|
||||||
|
#define MP_UNITS_EXPRESSION_WORKAROUND(x) x
|
||||||
|
#define MP_UNITS_IS_VALUE_WORKAROUND(x) x
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -30,9 +30,21 @@
|
|||||||
|
|
||||||
namespace mp_units::detail {
|
namespace mp_units::detail {
|
||||||
|
|
||||||
|
template<typename AlwaysVoid, typename... Ts>
|
||||||
|
struct has_common_type_impl : std::false_type {};
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
struct has_common_type_impl<std::void_t<std::common_type_t<Ts...>>, Ts...> : std::true_type {};
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
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>
|
template<typename T, typename Other>
|
||||||
using maybe_common_type = std::conditional_t<requires { typename std::common_type_t<T, Other>; },
|
using maybe_common_type =
|
||||||
std::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 Type-related details about the conversion from one quantity to another
|
* @brief Type-related details about the conversion from one quantity to another
|
||||||
|
@@ -68,7 +68,7 @@ struct type_list_map_impl<From<Args...>, To> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<TypeList From, template<typename...> typename To>
|
template<TypeList From, template<typename...> typename To>
|
||||||
using type_list_map = MP_UNITS_TYPENAME type_list_map_impl<From, To>::type;
|
using type_list_map = type_list_map_impl<From, To>::type;
|
||||||
|
|
||||||
|
|
||||||
// element
|
// element
|
||||||
@@ -105,7 +105,7 @@ struct type_list_front_impl<List<T, Ts...>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<TypeList List>
|
template<TypeList List>
|
||||||
using type_list_front = MP_UNITS_TYPENAME type_list_front_impl<List>::type;
|
using type_list_front = type_list_front_impl<List>::type;
|
||||||
|
|
||||||
// back
|
// back
|
||||||
template<TypeList List>
|
template<TypeList List>
|
||||||
@@ -121,7 +121,7 @@ struct type_list_push_front_impl<List<OldTypes...>, NewTypes...> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<TypeList List, typename... Types>
|
template<TypeList List, typename... Types>
|
||||||
using type_list_push_front = MP_UNITS_TYPENAME type_list_push_front_impl<List, Types...>::type;
|
using type_list_push_front = type_list_push_front_impl<List, Types...>::type;
|
||||||
|
|
||||||
// push_back
|
// push_back
|
||||||
template<typename List, typename... Types>
|
template<typename List, typename... Types>
|
||||||
@@ -133,7 +133,7 @@ struct type_list_push_back_impl<List<OldTypes...>, NewTypes...> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<TypeList List, typename... Types>
|
template<TypeList List, typename... Types>
|
||||||
using type_list_push_back = MP_UNITS_TYPENAME type_list_push_back_impl<List, Types...>::type;
|
using type_list_push_back = type_list_push_back_impl<List, Types...>::type;
|
||||||
|
|
||||||
// join
|
// join
|
||||||
template<typename List, typename... Rest>
|
template<typename List, typename... Rest>
|
||||||
@@ -143,11 +143,11 @@ struct type_list_join_impl {
|
|||||||
|
|
||||||
template<template<typename...> typename List, typename... First, typename... Second, typename... Rest>
|
template<template<typename...> typename List, typename... First, typename... Second, typename... Rest>
|
||||||
struct type_list_join_impl<List<First...>, List<Second...>, Rest...> {
|
struct type_list_join_impl<List<First...>, List<Second...>, Rest...> {
|
||||||
using type = MP_UNITS_TYPENAME type_list_join_impl<List<First..., Second...>, Rest...>::type;
|
using type = type_list_join_impl<List<First..., Second...>, Rest...>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<TypeList... Lists>
|
template<TypeList... Lists>
|
||||||
using type_list_join = MP_UNITS_TYPENAME type_list_join_impl<Lists...>::type;
|
using type_list_join = type_list_join_impl<Lists...>::type;
|
||||||
|
|
||||||
// split
|
// split
|
||||||
template<typename List, typename First, typename Second>
|
template<typename List, typename First, typename Second>
|
||||||
@@ -195,19 +195,19 @@ template<template<typename...> typename List, typename Lhs1, typename... LhsRest
|
|||||||
template<typename, typename> typename Pred>
|
template<typename, typename> typename Pred>
|
||||||
requires Pred<Lhs1, Rhs1>::value
|
requires Pred<Lhs1, Rhs1>::value
|
||||||
struct type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<Rhs1, RhsRest...>, Pred> {
|
struct type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<Rhs1, RhsRest...>, Pred> {
|
||||||
using type = MP_UNITS_TYPENAME type_list_push_front_impl<
|
using type = type_list_push_front_impl<
|
||||||
typename type_list_merge_sorted_impl<List<LhsRest...>, List<Rhs1, RhsRest...>, Pred>::type, Lhs1>::type;
|
typename type_list_merge_sorted_impl<List<LhsRest...>, List<Rhs1, RhsRest...>, Pred>::type, Lhs1>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<template<typename...> typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest,
|
template<template<typename...> typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest,
|
||||||
template<typename, typename> typename Pred>
|
template<typename, typename> typename Pred>
|
||||||
struct type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<Rhs1, RhsRest...>, Pred> {
|
struct type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<Rhs1, RhsRest...>, Pred> {
|
||||||
using type = MP_UNITS_TYPENAME type_list_push_front_impl<
|
using type = type_list_push_front_impl<
|
||||||
typename type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<RhsRest...>, Pred>::type, Rhs1>::type;
|
typename type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<RhsRest...>, Pred>::type, Rhs1>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<TypeList SortedList1, TypeList SortedList2, template<typename, typename> typename Pred>
|
template<TypeList SortedList1, TypeList SortedList2, template<typename, typename> typename Pred>
|
||||||
using type_list_merge_sorted = MP_UNITS_TYPENAME type_list_merge_sorted_impl<SortedList1, SortedList2, Pred>::type;
|
using type_list_merge_sorted = type_list_merge_sorted_impl<SortedList1, SortedList2, Pred>::type;
|
||||||
|
|
||||||
// sort
|
// sort
|
||||||
template<typename List, template<typename, typename> typename Pred>
|
template<typename List, template<typename, typename> typename Pred>
|
||||||
@@ -227,13 +227,13 @@ template<template<typename...> typename List, typename... Types, template<typena
|
|||||||
struct type_list_sort_impl<List<Types...>, Pred> {
|
struct type_list_sort_impl<List<Types...>, Pred> {
|
||||||
using types = List<Types...>;
|
using types = List<Types...>;
|
||||||
using split = type_list_split_half<List<Types...>>;
|
using split = type_list_split_half<List<Types...>>;
|
||||||
using sorted_left = MP_UNITS_TYPENAME type_list_sort_impl<typename split::first_list, Pred>::type;
|
using sorted_left = type_list_sort_impl<typename split::first_list, Pred>::type;
|
||||||
using sorted_right = MP_UNITS_TYPENAME type_list_sort_impl<typename split::second_list, Pred>::type;
|
using sorted_right = type_list_sort_impl<typename split::second_list, Pred>::type;
|
||||||
using type = MP_UNITS_TYPENAME type_list_merge_sorted_impl<sorted_left, sorted_right, Pred>::type;
|
using type = type_list_merge_sorted_impl<sorted_left, sorted_right, Pred>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<TypeList List, template<typename, typename> typename Pred>
|
template<TypeList List, template<typename, typename> typename Pred>
|
||||||
using type_list_sort = MP_UNITS_TYPENAME type_list_sort_impl<List, Pred>::type;
|
using type_list_sort = type_list_sort_impl<List, Pred>::type;
|
||||||
|
|
||||||
} // namespace mp_units::detail
|
} // namespace mp_units::detail
|
||||||
|
|
||||||
|
@@ -56,7 +56,7 @@ struct conditional_impl<true> {
|
|||||||
MP_UNITS_EXPORT_BEGIN
|
MP_UNITS_EXPORT_BEGIN
|
||||||
|
|
||||||
template<bool B, typename T, typename F>
|
template<bool B, typename T, typename F>
|
||||||
using conditional = MP_UNITS_TYPENAME detail::conditional_impl<B>::template type<T, F>;
|
using conditional = detail::conditional_impl<B>::template type<T, F>;
|
||||||
|
|
||||||
// is_same
|
// is_same
|
||||||
template<class T, class U>
|
template<class T, class U>
|
||||||
@@ -98,7 +98,7 @@ namespace detail {
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct get_value_type {
|
struct get_value_type {
|
||||||
using type = MP_UNITS_TYPENAME T::value_type;
|
using type = T::value_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -111,13 +111,13 @@ struct get_element_type {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
requires requires { typename T::value_type; } || requires { typename T::element_type; }
|
requires requires { typename T::value_type; } || requires { typename T::element_type; }
|
||||||
struct wrapped_type {
|
struct wrapped_type {
|
||||||
using type = MP_UNITS_TYPENAME
|
using type =
|
||||||
conditional<requires { typename T::value_type; }, detail::get_value_type<T>, detail::get_element_type<T>>::type;
|
conditional<requires { typename T::value_type; }, detail::get_value_type<T>, detail::get_element_type<T>>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
requires requires { typename T::value_type; } || requires { typename T::element_type; }
|
requires requires { typename T::value_type; } || requires { typename T::element_type; }
|
||||||
using wrapped_type_t = MP_UNITS_TYPENAME wrapped_type<T>::type;
|
using wrapped_type_t = wrapped_type<T>::type;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct value_type {
|
struct value_type {
|
||||||
@@ -127,11 +127,11 @@ struct value_type {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
requires requires { typename wrapped_type_t<T>; }
|
requires requires { typename wrapped_type_t<T>; }
|
||||||
struct value_type<T> {
|
struct value_type<T> {
|
||||||
using type = MP_UNITS_TYPENAME wrapped_type_t<T>;
|
using type = wrapped_type_t<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using value_type_t = MP_UNITS_TYPENAME value_type<T>::type;
|
using value_type_t = value_type<T>::type;
|
||||||
|
|
||||||
template<typename T, typename... Ts>
|
template<typename T, typename... Ts>
|
||||||
concept one_of = (false || ... || std::same_as<T, Ts>);
|
concept one_of = (false || ... || std::same_as<T, Ts>);
|
||||||
|
@@ -47,8 +47,8 @@ namespace mp_units::detail {
|
|||||||
template<typename Char>
|
template<typename Char>
|
||||||
[[nodiscard]] constexpr const Char* at_most_one_of(const Char* begin, const Char* end, std::string_view modifiers)
|
[[nodiscard]] constexpr const Char* at_most_one_of(const Char* begin, const Char* end, std::string_view modifiers)
|
||||||
{
|
{
|
||||||
const Char* const it = find_first_of(begin, end, modifiers.begin(), modifiers.end());
|
const Char* const it = mp_units::detail::find_first_of(begin, end, modifiers.begin(), modifiers.end());
|
||||||
if (it != end && find_first_of(it + 1, end, modifiers.begin(), modifiers.end()) != end)
|
if (it != end && mp_units::detail::find_first_of(it + 1, end, modifiers.begin(), modifiers.end()) != end)
|
||||||
throw MP_UNITS_STD_FMT::format_error("only one of '" + std::string(modifiers) +
|
throw MP_UNITS_STD_FMT::format_error("only one of '" + std::string(modifiers) +
|
||||||
"' unit modifiers may be used in the format spec");
|
"' unit modifiers may be used in the format spec");
|
||||||
return it;
|
return it;
|
||||||
@@ -452,7 +452,7 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
|
|||||||
}
|
}
|
||||||
// user provided format
|
// user provided format
|
||||||
quantity_formatter f{*this, out, q, locale};
|
quantity_formatter f{*this, out, q, locale};
|
||||||
parse_quantity_specs(modifiers_format_str_.begin(), modifiers_format_str_.end(), f);
|
parse_quantity_specs(modifiers_format_str_.data(), modifiers_format_str_.data() + modifiers_format_str_.size(), f);
|
||||||
return f.out;
|
return f.out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,7 +40,7 @@ namespace mp_units {
|
|||||||
template<Reference R>
|
template<Reference R>
|
||||||
struct delta_ {
|
struct delta_ {
|
||||||
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
|
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
|
||||||
[[nodiscard]] constexpr quantity<R{}, Rep> operator()(FwdRep&& lhs) const
|
[[nodiscard]] constexpr quantity<MP_UNITS_EXPRESSION_WORKAROUND(R{}), Rep> operator()(FwdRep&& lhs) const
|
||||||
{
|
{
|
||||||
return quantity{std::forward<FwdRep>(lhs), R{}};
|
return quantity{std::forward<FwdRep>(lhs), R{}};
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,8 @@ struct delta_ {
|
|||||||
template<Reference R>
|
template<Reference R>
|
||||||
struct absolute_ {
|
struct absolute_ {
|
||||||
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
|
template<typename FwdRep, RepresentationOf<get_quantity_spec(R{}).character> Rep = std::remove_cvref_t<FwdRep>>
|
||||||
[[nodiscard]] constexpr quantity_point<R{}, default_point_origin(R{}), Rep> operator()(FwdRep&& lhs) const
|
[[nodiscard]] constexpr quantity_point<MP_UNITS_EXPRESSION_WORKAROUND(R{}), default_point_origin(R{}), Rep>
|
||||||
|
operator()(FwdRep&& lhs) const
|
||||||
{
|
{
|
||||||
return quantity_point{quantity{std::forward<FwdRep>(lhs), R{}}};
|
return quantity_point{quantity{std::forward<FwdRep>(lhs), R{}}};
|
||||||
}
|
}
|
||||||
|
@@ -54,7 +54,7 @@ void to_base_specialization_of_base_dimension(const volatile base_dimension<Symb
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool is_derived_from_specialization_of_base_dimension =
|
constexpr bool is_derived_from_specialization_of_base_dimension =
|
||||||
requires(T* t) { to_base_specialization_of_base_dimension(t); };
|
requires(T* type) { to_base_specialization_of_base_dimension(type); };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A concept matching all named base dimensions in the library.
|
* @brief A concept matching all named base dimensions in the library.
|
||||||
|
@@ -122,7 +122,7 @@ struct expr_type_impl<power<T, Ints...>> : std::type_identity<T> {};
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using expr_type = MP_UNITS_TYPENAME detail::expr_type_impl<T>::type;
|
using expr_type = detail::expr_type_impl<T>::type;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
@@ -182,25 +182,24 @@ struct expr_consolidate_impl<type_list<T, Rest...>> {
|
|||||||
template<typename T, typename... Rest>
|
template<typename T, typename... Rest>
|
||||||
requires(!is_specialization_of_power<T>)
|
requires(!is_specialization_of_power<T>)
|
||||||
struct expr_consolidate_impl<type_list<T, T, Rest...>> {
|
struct expr_consolidate_impl<type_list<T, T, Rest...>> {
|
||||||
using type = MP_UNITS_TYPENAME expr_consolidate_impl<type_list<power<T, 2>, Rest...>>::type;
|
using type = expr_consolidate_impl<type_list<power<T, 2>, Rest...>>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
// replaces the instance of a type and a power of it with one with incremented power
|
// replaces the instance of a type and a power of it with one with incremented power
|
||||||
template<typename T, int... Ints, typename... Rest>
|
template<typename T, int... Ints, typename... Rest>
|
||||||
struct expr_consolidate_impl<type_list<T, power<T, Ints...>, Rest...>> {
|
struct expr_consolidate_impl<type_list<T, power<T, Ints...>, Rest...>> {
|
||||||
using type =
|
using type = expr_consolidate_impl<type_list<power_or_T<T, power<T, Ints...>::exponent + 1>, Rest...>>::type;
|
||||||
MP_UNITS_TYPENAME expr_consolidate_impl<type_list<power_or_T<T, power<T, Ints...>::exponent + 1>, Rest...>>::type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// accumulates the powers of instances of the same type (removes the element in case the accumulation result is `0`)
|
// accumulates the powers of instances of the same type (removes the element in case the accumulation result is `0`)
|
||||||
template<typename T, int... Ints1, int... Ints2, typename... Rest>
|
template<typename T, int... Ints1, int... Ints2, typename... Rest>
|
||||||
struct expr_consolidate_impl<type_list<power<T, Ints1...>, power<T, Ints2...>, Rest...>> {
|
struct expr_consolidate_impl<type_list<power<T, Ints1...>, power<T, Ints2...>, Rest...>> {
|
||||||
static constexpr ratio r = power<T, Ints1...>::exponent + power<T, Ints2...>::exponent;
|
static constexpr ratio r = power<T, Ints1...>::exponent + power<T, Ints2...>::exponent;
|
||||||
using type = MP_UNITS_TYPENAME expr_consolidate_impl<type_list<power_or_T<T, r>, Rest...>>::type;
|
using type = expr_consolidate_impl<type_list<power_or_T<T, r>, Rest...>>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename List>
|
template<typename List>
|
||||||
using expr_consolidate = MP_UNITS_TYPENAME expr_consolidate_impl<List>::type;
|
using expr_consolidate = expr_consolidate_impl<List>::type;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -707,7 +707,8 @@ template<auto... Ms>
|
|||||||
void to_base_specialization_of_magnitude(const volatile magnitude<Ms...>*);
|
void to_base_specialization_of_magnitude(const volatile magnitude<Ms...>*);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool is_derived_from_specialization_of_magnitude = requires(T* t) { to_base_specialization_of_magnitude(t); };
|
constexpr bool is_derived_from_specialization_of_magnitude =
|
||||||
|
requires(T* type) { to_base_specialization_of_magnitude(type); };
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
requires is_derived_from_specialization_of_magnitude<T>
|
requires is_derived_from_specialization_of_magnitude<T>
|
||||||
|
@@ -435,7 +435,9 @@ public:
|
|||||||
}
|
}
|
||||||
friend constexpr decltype(auto) operator*=(FwdQ&& lhs, const Value& v)
|
friend constexpr decltype(auto) operator*=(FwdQ&& lhs, const Value& v)
|
||||||
{
|
{
|
||||||
lhs.numerical_value_is_an_implementation_detail_ *= v;
|
// TODO use *= when compiiler bug is resolved:
|
||||||
|
// https://developercommunity.visualstudio.com/t/Discrepancy-in-Behavior-of-operator-an/10732445
|
||||||
|
lhs.numerical_value_is_an_implementation_detail_ = lhs.numerical_value_is_an_implementation_detail_ * v;
|
||||||
return std::forward<FwdQ>(lhs);
|
return std::forward<FwdQ>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,7 +449,10 @@ public:
|
|||||||
}
|
}
|
||||||
friend constexpr decltype(auto) operator*=(FwdQ1&& lhs, const Q2& rhs)
|
friend constexpr decltype(auto) operator*=(FwdQ1&& lhs, const Q2& rhs)
|
||||||
{
|
{
|
||||||
lhs.numerical_value_is_an_implementation_detail_ *= rhs.numerical_value_is_an_implementation_detail_;
|
// TODO use *= when compiiler bug is resolved:
|
||||||
|
// https://developercommunity.visualstudio.com/t/Discrepancy-in-Behavior-of-operator-an/10732445
|
||||||
|
lhs.numerical_value_is_an_implementation_detail_ =
|
||||||
|
lhs.numerical_value_is_an_implementation_detail_ * rhs.numerical_value_is_an_implementation_detail_;
|
||||||
return std::forward<FwdQ1>(lhs);
|
return std::forward<FwdQ1>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,7 +465,9 @@ public:
|
|||||||
friend constexpr decltype(auto) operator/=(FwdQ&& lhs, const Value& v)
|
friend constexpr decltype(auto) operator/=(FwdQ&& lhs, const Value& v)
|
||||||
{
|
{
|
||||||
MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero());
|
MP_UNITS_EXPECTS_DEBUG(v != quantity_values<Value>::zero());
|
||||||
lhs.numerical_value_is_an_implementation_detail_ /= v;
|
// TODO use /= when compiiler bug is resolved:
|
||||||
|
// https://developercommunity.visualstudio.com/t/Discrepancy-in-Behavior-of-operator-an/10732445
|
||||||
|
lhs.numerical_value_is_an_implementation_detail_ = lhs.numerical_value_is_an_implementation_detail_ / v;
|
||||||
return std::forward<FwdQ>(lhs);
|
return std::forward<FwdQ>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,7 +480,10 @@ public:
|
|||||||
friend constexpr decltype(auto) operator/=(FwdQ1&& lhs, const Q2& rhs)
|
friend constexpr decltype(auto) operator/=(FwdQ1&& lhs, const Q2& rhs)
|
||||||
{
|
{
|
||||||
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
|
MP_UNITS_EXPECTS_DEBUG(rhs != rhs.zero());
|
||||||
lhs.numerical_value_is_an_implementation_detail_ /= rhs.numerical_value_is_an_implementation_detail_;
|
// TODO use /= when compiiler bug is resolved:
|
||||||
|
// https://developercommunity.visualstudio.com/t/Discrepancy-in-Behavior-of-operator-an/10732445
|
||||||
|
lhs.numerical_value_is_an_implementation_detail_ =
|
||||||
|
lhs.numerical_value_is_an_implementation_detail_ / rhs.numerical_value_is_an_implementation_detail_;
|
||||||
return std::forward<FwdQ1>(lhs);
|
return std::forward<FwdQ1>(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,7 +40,8 @@ template<auto R, typename Rep>
|
|||||||
void to_base_specialization_of_quantity(const volatile quantity<R, Rep>*);
|
void to_base_specialization_of_quantity(const volatile quantity<R, Rep>*);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool is_derived_from_specialization_of_quantity = requires(T* t) { to_base_specialization_of_quantity(t); };
|
constexpr bool is_derived_from_specialization_of_quantity =
|
||||||
|
requires(T* type) { to_base_specialization_of_quantity(type); };
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
@@ -53,13 +53,15 @@ template<PointOrigin PO>
|
|||||||
|
|
||||||
struct point_origin_interface {
|
struct point_origin_interface {
|
||||||
template<PointOrigin PO, typename FwdQ, QuantityOf<PO::quantity_spec> Q = std::remove_cvref_t<FwdQ>>
|
template<PointOrigin PO, typename FwdQ, QuantityOf<PO::quantity_spec> Q = std::remove_cvref_t<FwdQ>>
|
||||||
[[nodiscard]] friend constexpr quantity_point<Q::reference, PO{}, typename Q::rep> operator+(PO, FwdQ&& q)
|
[[nodiscard]] friend constexpr quantity_point<Q::reference, MP_UNITS_EXPRESSION_WORKAROUND(PO{}), typename Q::rep>
|
||||||
|
operator+(PO, FwdQ&& q)
|
||||||
{
|
{
|
||||||
return quantity_point{std::forward<FwdQ>(q), PO{}};
|
return quantity_point{std::forward<FwdQ>(q), PO{}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Quantity FwdQ, PointOrigin PO, QuantityOf<PO::quantity_spec> Q = std::remove_cvref_t<FwdQ>>
|
template<Quantity FwdQ, PointOrigin PO, QuantityOf<PO::quantity_spec> Q = std::remove_cvref_t<FwdQ>>
|
||||||
[[nodiscard]] friend constexpr quantity_point<Q::reference, PO{}, typename Q::rep> operator+(FwdQ&& q, PO po)
|
[[nodiscard]] friend constexpr quantity_point<Q::reference, MP_UNITS_EXPRESSION_WORKAROUND(PO{}), typename Q::rep>
|
||||||
|
operator+(FwdQ&& q, PO po)
|
||||||
{
|
{
|
||||||
return po + std::forward<FwdQ>(q);
|
return po + std::forward<FwdQ>(q);
|
||||||
}
|
}
|
||||||
@@ -261,10 +263,9 @@ public:
|
|||||||
quantity_point& operator=(quantity_point&&) = default;
|
quantity_point& operator=(quantity_point&&) = default;
|
||||||
|
|
||||||
template<detail::SameAbsolutePointOriginAs<absolute_point_origin> NewPO>
|
template<detail::SameAbsolutePointOriginAs<absolute_point_origin> NewPO>
|
||||||
[[nodiscard]] constexpr MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(QuantityPointOf<NewPO{}>) auto point_for(
|
[[nodiscard]] constexpr QuantityPointOf<(NewPO{})> auto point_for(NewPO new_origin) const
|
||||||
NewPO new_origin) const
|
|
||||||
{
|
{
|
||||||
if constexpr (is_same_v<NewPO, decltype(PO)>)
|
if constexpr (is_same_v<NewPO, decltype(point_origin)>)
|
||||||
return *this;
|
return *this;
|
||||||
else
|
else
|
||||||
return ::mp_units::quantity_point{*this - new_origin, new_origin};
|
return ::mp_units::quantity_point{*this - new_origin, new_origin};
|
||||||
@@ -326,42 +327,42 @@ public:
|
|||||||
requires detail::QuantityConvertibleTo<quantity_type, quantity<detail::make_reference(quantity_spec, ToU{}), Rep>>
|
requires detail::QuantityConvertibleTo<quantity_type, quantity<detail::make_reference(quantity_spec, ToU{}), Rep>>
|
||||||
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto in(ToU) const
|
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto in(ToU) const
|
||||||
{
|
{
|
||||||
return ::mp_units::quantity_point{quantity_ref_from(PO).in(ToU{}), PO};
|
return ::mp_units::quantity_point{quantity_ref_from(point_origin).in(ToU{}), point_origin};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<RepresentationOf<quantity_spec.character> ToRep>
|
template<RepresentationOf<quantity_spec.character> ToRep>
|
||||||
requires detail::QuantityConvertibleTo<quantity_type, quantity<reference, ToRep>>
|
requires detail::QuantityConvertibleTo<quantity_type, quantity<reference, ToRep>>
|
||||||
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto in() const
|
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto in() const
|
||||||
{
|
{
|
||||||
return ::mp_units::quantity_point{quantity_ref_from(PO).template in<ToRep>(), PO};
|
return ::mp_units::quantity_point{quantity_ref_from(point_origin).template in<ToRep>(), point_origin};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<RepresentationOf<quantity_spec.character> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
|
template<RepresentationOf<quantity_spec.character> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
|
||||||
requires detail::QuantityConvertibleTo<quantity_type, quantity<detail::make_reference(quantity_spec, ToU{}), ToRep>>
|
requires detail::QuantityConvertibleTo<quantity_type, quantity<detail::make_reference(quantity_spec, ToU{}), ToRep>>
|
||||||
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto in(ToU) const
|
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto in(ToU) const
|
||||||
{
|
{
|
||||||
return ::mp_units::quantity_point{quantity_ref_from(PO).template in<ToRep>(ToU{}), PO};
|
return ::mp_units::quantity_point{quantity_ref_from(point_origin).template in<ToRep>(ToU{}), point_origin};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<detail::UnitCompatibleWith<unit, quantity_spec> ToU>
|
template<detail::UnitCompatibleWith<unit, quantity_spec> ToU>
|
||||||
requires requires(quantity_type q) { value_cast<ToU{}>(q); }
|
requires requires(quantity_type q) { value_cast<ToU{}>(q); }
|
||||||
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const
|
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const
|
||||||
{
|
{
|
||||||
return ::mp_units::quantity_point{quantity_ref_from(PO).force_in(ToU{}), PO};
|
return ::mp_units::quantity_point{quantity_ref_from(point_origin).force_in(ToU{}), point_origin};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<RepresentationOf<quantity_spec.character> ToRep>
|
template<RepresentationOf<quantity_spec.character> ToRep>
|
||||||
requires requires(quantity_type q) { value_cast<ToRep>(q); }
|
requires requires(quantity_type q) { value_cast<ToRep>(q); }
|
||||||
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto force_in() const
|
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto force_in() const
|
||||||
{
|
{
|
||||||
return ::mp_units::quantity_point{quantity_ref_from(PO).template force_in<ToRep>(), PO};
|
return ::mp_units::quantity_point{quantity_ref_from(point_origin).template force_in<ToRep>(), point_origin};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<RepresentationOf<quantity_spec.character> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
|
template<RepresentationOf<quantity_spec.character> ToRep, detail::UnitCompatibleWith<unit, quantity_spec> ToU>
|
||||||
requires requires(quantity_type q) { value_cast<ToU{}, ToRep>(q); }
|
requires requires(quantity_type q) { value_cast<ToU{}, ToRep>(q); }
|
||||||
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const
|
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const
|
||||||
{
|
{
|
||||||
return ::mp_units::quantity_point{quantity_ref_from(PO).template force_in<ToRep>(ToU{}), PO};
|
return ::mp_units::quantity_point{quantity_ref_from(point_origin).template force_in<ToRep>(ToU{}), point_origin};
|
||||||
}
|
}
|
||||||
|
|
||||||
// conversion operators
|
// conversion operators
|
||||||
|
@@ -45,7 +45,7 @@ void to_base_specialization_of_absolute_point_origin(const volatile absolute_poi
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool is_derived_from_specialization_of_absolute_point_origin =
|
constexpr bool is_derived_from_specialization_of_absolute_point_origin =
|
||||||
requires(T* t) { to_base_specialization_of_absolute_point_origin(t); };
|
requires(T* type) { to_base_specialization_of_absolute_point_origin(type); };
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ void to_base_specialization_of_relative_point_origin(const volatile relative_poi
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool is_derived_from_specialization_of_relative_point_origin =
|
constexpr bool is_derived_from_specialization_of_relative_point_origin =
|
||||||
requires(T* t) { to_base_specialization_of_relative_point_origin(t); };
|
requires(T* type) { to_base_specialization_of_relative_point_origin(type); };
|
||||||
|
|
||||||
struct point_origin_interface;
|
struct point_origin_interface;
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ void to_base_specialization_of_quantity_point(const volatile quantity_point<R, P
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool is_derived_from_specialization_of_quantity_point =
|
constexpr bool is_derived_from_specialization_of_quantity_point =
|
||||||
requires(T* t) { to_base_specialization_of_quantity_point(t); };
|
requires(T* type) { to_base_specialization_of_quantity_point(type); };
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
requires is_derived_from_specialization_of_quantity_point<T>
|
requires is_derived_from_specialization_of_quantity_point<T>
|
||||||
|
@@ -667,11 +667,11 @@ template<QuantitySpec Q>
|
|||||||
// dimension_one is always the last one
|
// dimension_one is always the last one
|
||||||
// otherwise, sort by typename
|
// otherwise, sort by typename
|
||||||
template<Dimension D1, Dimension D2>
|
template<Dimension D1, Dimension D2>
|
||||||
[[nodiscard]] consteval bool ingredients_dimension_less(D1 lhs, D2 rhs)
|
[[nodiscard]] consteval bool ingredients_dimension_less(D1, D2)
|
||||||
{
|
{
|
||||||
if constexpr (lhs == rhs || lhs == dimension_one)
|
if constexpr (D1{} == D2{} || D1{} == dimension_one)
|
||||||
return false;
|
return false;
|
||||||
else if constexpr (rhs == dimension_one)
|
else if constexpr (D2{} == dimension_one)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return detail::type_name<D1>() < detail::type_name<D2>();
|
return detail::type_name<D1>() < detail::type_name<D2>();
|
||||||
@@ -760,15 +760,15 @@ template<int Complexity, NamedQuantitySpec Q>
|
|||||||
template<int Complexity, QuantitySpec Q, typename Num, typename... Nums, typename Den, typename... Dens>
|
template<int Complexity, QuantitySpec Q, typename Num, typename... Nums, typename Den, typename... Dens>
|
||||||
[[nodiscard]] consteval auto explode(Q, type_list<Num, Nums...>, type_list<Den, Dens...>)
|
[[nodiscard]] consteval auto explode(Q, type_list<Num, Nums...>, type_list<Den, Dens...>)
|
||||||
{
|
{
|
||||||
constexpr auto n = get_complexity(Num{});
|
constexpr auto num = get_complexity(Num{});
|
||||||
constexpr auto d = get_complexity(Den{});
|
constexpr auto den = get_complexity(Den{});
|
||||||
constexpr auto max_compl = n > d ? n : d;
|
constexpr auto max_compl = num > den ? num : den;
|
||||||
|
|
||||||
if constexpr (max_compl == Complexity || ((n >= d && !requires { explode_to_equation(Num{}); }) ||
|
if constexpr (max_compl == Complexity || ((num >= den && !requires { explode_to_equation(Num{}); }) ||
|
||||||
(n < d && !requires { explode_to_equation(Den{}); })))
|
(num < den && !requires { explode_to_equation(Den{}); })))
|
||||||
return explode_result{(map_power(Num{}) * ... * map_power(Nums{})) / (map_power(Den{}) * ... * map_power(Dens{}))};
|
return explode_result{(map_power(Num{}) * ... * map_power(Nums{})) / (map_power(Den{}) * ... * map_power(Dens{}))};
|
||||||
else {
|
else {
|
||||||
if constexpr (n >= d) {
|
if constexpr (num >= den) {
|
||||||
constexpr auto res = explode_to_equation(Num{});
|
constexpr auto res = explode_to_equation(Num{});
|
||||||
return explode<Complexity>((res.equation * ... * map_power(Nums{})) /
|
return explode<Complexity>((res.equation * ... * map_power(Nums{})) /
|
||||||
(map_power(Den{}) * ... * map_power(Dens{})))
|
(map_power(Den{}) * ... * map_power(Dens{})))
|
||||||
@@ -797,8 +797,8 @@ template<int Complexity, QuantitySpec Q, typename Num, typename... Nums>
|
|||||||
template<int Complexity, QuantitySpec Q, typename Den, typename... Dens>
|
template<int Complexity, QuantitySpec Q, typename Den, typename... Dens>
|
||||||
[[nodiscard]] consteval auto explode(Q, type_list<>, type_list<Den, Dens...>)
|
[[nodiscard]] consteval auto explode(Q, type_list<>, type_list<Den, Dens...>)
|
||||||
{
|
{
|
||||||
constexpr auto d = get_complexity(Den{});
|
constexpr auto den = get_complexity(Den{});
|
||||||
if constexpr (d == Complexity || !requires { explode_to_equation(Den{}); })
|
if constexpr (den == Complexity || !requires { explode_to_equation(Den{}); })
|
||||||
return explode_result{dimensionless / (map_power(Den{}) * ... * map_power(Dens{}))};
|
return explode_result{dimensionless / (map_power(Den{}) * ... * map_power(Dens{}))};
|
||||||
else {
|
else {
|
||||||
constexpr auto res = explode_to_equation(Den{});
|
constexpr auto res = explode_to_equation(Den{});
|
||||||
@@ -816,8 +816,8 @@ template<int Complexity, QuantitySpec Q>
|
|||||||
template<int Complexity, DerivedQuantitySpec Q>
|
template<int Complexity, DerivedQuantitySpec Q>
|
||||||
[[nodiscard]] consteval auto explode(Q q)
|
[[nodiscard]] consteval auto explode(Q q)
|
||||||
{
|
{
|
||||||
constexpr auto c = get_complexity(Q{});
|
constexpr auto complexity = get_complexity(Q{});
|
||||||
if constexpr (c > Complexity)
|
if constexpr (complexity > Complexity)
|
||||||
return explode<Complexity>(q, type_list_sort<typename Q::_num_, type_list_of_ingredients_less>{},
|
return explode<Complexity>(q, type_list_sort<typename Q::_num_, type_list_of_ingredients_less>{},
|
||||||
type_list_sort<typename Q::_den_, type_list_of_ingredients_less>{});
|
type_list_sort<typename Q::_den_, type_list_of_ingredients_less>{});
|
||||||
else
|
else
|
||||||
@@ -827,8 +827,8 @@ template<int Complexity, DerivedQuantitySpec Q>
|
|||||||
template<int Complexity, NamedQuantitySpec Q>
|
template<int Complexity, NamedQuantitySpec Q>
|
||||||
[[nodiscard]] consteval auto explode(Q q)
|
[[nodiscard]] consteval auto explode(Q q)
|
||||||
{
|
{
|
||||||
constexpr auto c = get_complexity(Q{});
|
constexpr auto complexity = get_complexity(Q{});
|
||||||
if constexpr (c > Complexity && requires { Q::_equation_; }) {
|
if constexpr (complexity > Complexity && requires { Q::_equation_; }) {
|
||||||
constexpr auto res = explode_to_equation(Q{});
|
constexpr auto res = explode_to_equation(Q{});
|
||||||
return explode<Complexity>(res.equation).common_convertibility_with(res);
|
return explode<Complexity>(res.equation).common_convertibility_with(res);
|
||||||
} else
|
} else
|
||||||
@@ -1340,15 +1340,15 @@ template<QuantitySpec From, QuantitySpec To>
|
|||||||
using enum specs_convertible_result;
|
using enum specs_convertible_result;
|
||||||
return res == no ? no : yes;
|
return res == no ? no : yes;
|
||||||
};
|
};
|
||||||
if constexpr ((NamedQuantitySpec<decltype(from_kind)> && NamedQuantitySpec<decltype(to_kind)>) ||
|
if constexpr ((NamedQuantitySpec<decltype(From{})> && NamedQuantitySpec<decltype(To{})>) ||
|
||||||
get_complexity(from_kind) == get_complexity(to_kind))
|
get_complexity(From{}) == get_complexity(To{}))
|
||||||
return convertible_impl(from_kind, to_kind);
|
return convertible_impl(from_kind, to_kind);
|
||||||
else if constexpr (get_complexity(from_kind) > get_complexity(to_kind))
|
else if constexpr (get_complexity(From{}) > get_complexity(To{}))
|
||||||
return exploded_kind_result(
|
return exploded_kind_result(
|
||||||
convertible_impl(get_kind_tree_root(explode<get_complexity(to_kind)>(from_kind).quantity), to_kind));
|
convertible_impl(get_kind_tree_root(explode<get_complexity(To{})>(from_kind).quantity), to_kind));
|
||||||
else
|
else
|
||||||
return exploded_kind_result(
|
return exploded_kind_result(
|
||||||
convertible_impl(from_kind, get_kind_tree_root(explode<get_complexity(from_kind)>(to_kind).quantity)));
|
convertible_impl(from_kind, get_kind_tree_root(explode<get_complexity(From{})>(to_kind).quantity)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<NamedQuantitySpec From, NamedQuantitySpec To>
|
template<NamedQuantitySpec From, NamedQuantitySpec To>
|
||||||
@@ -1365,9 +1365,9 @@ template<NamedQuantitySpec From, NamedQuantitySpec To>
|
|||||||
return no;
|
return no;
|
||||||
else if constexpr (get_complexity(From{}) != get_complexity(To{})) {
|
else if constexpr (get_complexity(From{}) != get_complexity(To{})) {
|
||||||
if constexpr (get_complexity(From{}) > get_complexity(To{}))
|
if constexpr (get_complexity(From{}) > get_complexity(To{}))
|
||||||
return convertible_impl(explode<get_complexity(to)>(from).quantity, to);
|
return convertible_impl(explode<get_complexity(To{})>(from).quantity, to);
|
||||||
else {
|
else {
|
||||||
auto res = explode<get_complexity(from)>(to);
|
auto res = explode<get_complexity(From{})>(to);
|
||||||
return min(res.result, convertible_impl(from, res.quantity));
|
return min(res.result, convertible_impl(from, res.quantity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1392,7 +1392,7 @@ template<QuantitySpec From, QuantitySpec To>
|
|||||||
else if constexpr (DerivedQuantitySpec<From> && DerivedQuantitySpec<To>)
|
else if constexpr (DerivedQuantitySpec<From> && DerivedQuantitySpec<To>)
|
||||||
return are_ingredients_convertible(from, to);
|
return are_ingredients_convertible(from, to);
|
||||||
else if constexpr (DerivedQuantitySpec<From>) {
|
else if constexpr (DerivedQuantitySpec<From>) {
|
||||||
auto res = explode<get_complexity(to)>(from);
|
auto res = explode<get_complexity(To{})>(from);
|
||||||
if constexpr (NamedQuantitySpec<decltype(res.quantity)>)
|
if constexpr (NamedQuantitySpec<decltype(res.quantity)>)
|
||||||
return convertible_impl(res.quantity, to);
|
return convertible_impl(res.quantity, to);
|
||||||
else if constexpr (requires { to._equation_; }) {
|
else if constexpr (requires { to._equation_; }) {
|
||||||
@@ -1401,7 +1401,7 @@ template<QuantitySpec From, QuantitySpec To>
|
|||||||
} else
|
} else
|
||||||
return are_ingredients_convertible(from, to);
|
return are_ingredients_convertible(from, to);
|
||||||
} else if constexpr (DerivedQuantitySpec<To>) {
|
} else if constexpr (DerivedQuantitySpec<To>) {
|
||||||
auto res = explode<get_complexity(from)>(to);
|
auto res = explode<get_complexity(From{})>(to);
|
||||||
if constexpr (NamedQuantitySpec<decltype(res.quantity)>)
|
if constexpr (NamedQuantitySpec<decltype(res.quantity)>)
|
||||||
return min(res.result, convertible_impl(from, res.quantity));
|
return min(res.result, convertible_impl(from, res.quantity));
|
||||||
else if constexpr (requires { from._equation_; })
|
else if constexpr (requires { from._equation_; })
|
||||||
@@ -1492,9 +1492,9 @@ template<QuantitySpec Q>
|
|||||||
MP_UNITS_EXPORT_BEGIN
|
MP_UNITS_EXPORT_BEGIN
|
||||||
|
|
||||||
template<QuantitySpec Q>
|
template<QuantitySpec Q>
|
||||||
[[nodiscard]] consteval detail::QuantityKindSpec auto get_kind(Q q)
|
[[nodiscard]] consteval detail::QuantityKindSpec auto get_kind(Q)
|
||||||
{
|
{
|
||||||
return kind_of<detail::get_kind_tree_root(q)>;
|
return kind_of<detail::get_kind_tree_root(Q{})>;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] consteval QuantitySpec auto common_quantity_spec(QuantitySpec auto q) { return q; }
|
[[nodiscard]] consteval QuantitySpec auto common_quantity_spec(QuantitySpec auto q) { return q; }
|
||||||
|
@@ -71,7 +71,7 @@ void to_base_specialization_of_quantity_spec(const volatile quantity_spec<T, Arg
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool is_derived_from_specialization_of_quantity_spec =
|
constexpr bool is_derived_from_specialization_of_quantity_spec =
|
||||||
requires(T* t) { to_base_specialization_of_quantity_spec(t); };
|
requires(T* type) { to_base_specialization_of_quantity_spec(type); };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Concept matching all named quantity specification types
|
* @brief Concept matching all named quantity specification types
|
||||||
|
@@ -87,37 +87,49 @@ struct reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Q2, typename U2>
|
template<typename Q2, typename U2>
|
||||||
[[nodiscard]] friend consteval detail::reference_t<Q{} * Q2{}, U{} * U2{}> operator*(reference, reference<Q2, U2>)
|
[[nodiscard]] friend consteval detail::reference_t<MP_UNITS_EXPRESSION_WORKAROUND(Q{} * Q2{}),
|
||||||
|
MP_UNITS_EXPRESSION_WORKAROUND(U{} * U2{})>
|
||||||
|
operator*(reference, reference<Q2, U2>)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<AssociatedUnit U2>
|
template<AssociatedUnit U2>
|
||||||
[[nodiscard]] friend consteval detail::reference_t<Q{} * get_quantity_spec(U2{}), U{} * U2{}> operator*(reference, U2)
|
[[nodiscard]] friend consteval detail::reference_t<(MP_UNITS_EXPRESSION_WORKAROUND(Q{} * get_quantity_spec(U2{}))),
|
||||||
|
MP_UNITS_EXPRESSION_WORKAROUND(U{} * U2{})>
|
||||||
|
operator*(reference, U2)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<AssociatedUnit U1>
|
template<AssociatedUnit U1>
|
||||||
[[nodiscard]] friend consteval detail::reference_t<get_quantity_spec(U1{}) * Q{}, U1{} * U{}> operator*(U1, reference)
|
[[nodiscard]] friend consteval detail::reference_t<MP_UNITS_EXPRESSION_WORKAROUND(get_quantity_spec(U1{}) * Q{}),
|
||||||
|
MP_UNITS_EXPRESSION_WORKAROUND(U1{} * U{})>
|
||||||
|
operator*(U1, reference)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Q2, typename U2>
|
template<typename Q2, typename U2>
|
||||||
[[nodiscard]] friend consteval detail::reference_t<Q{} / Q2{}, U{} / U2{}> operator/(reference, reference<Q2, U2>)
|
[[nodiscard]] friend consteval detail::reference_t<MP_UNITS_EXPRESSION_WORKAROUND(Q{} / Q2{}),
|
||||||
|
MP_UNITS_EXPRESSION_WORKAROUND(U{} / U2{})>
|
||||||
|
operator/(reference, reference<Q2, U2>)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<AssociatedUnit U2>
|
template<AssociatedUnit U2>
|
||||||
[[nodiscard]] friend consteval detail::reference_t<Q{} / get_quantity_spec(U2{}), U{} / U2{}> operator/(reference, U2)
|
[[nodiscard]] friend consteval detail::reference_t<MP_UNITS_EXPRESSION_WORKAROUND(Q{} / get_quantity_spec(U2{})),
|
||||||
|
MP_UNITS_EXPRESSION_WORKAROUND(U{} / U2{})>
|
||||||
|
operator/(reference, U2)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<AssociatedUnit U1>
|
template<AssociatedUnit U1>
|
||||||
[[nodiscard]] friend consteval detail::reference_t<get_quantity_spec(U1{}) / Q{}, U1{} / U{}> operator/(U1, reference)
|
[[nodiscard]] friend consteval detail::reference_t<MP_UNITS_EXPRESSION_WORKAROUND(get_quantity_spec(U1{}) / Q{}),
|
||||||
|
MP_UNITS_EXPRESSION_WORKAROUND(U1{} / U{})>
|
||||||
|
operator/(U1, reference)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -281,9 +293,9 @@ template<Reference R1, Reference R2, Reference... Rest>
|
|||||||
} -> Unit;
|
} -> Unit;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
return detail::reference_t<common_quantity_spec(get_quantity_spec(r1), get_quantity_spec(r2),
|
return detail::reference_t<common_quantity_spec(get_quantity_spec(R1{}), get_quantity_spec(R2{}),
|
||||||
get_quantity_spec(rest)...),
|
get_quantity_spec(rest)...),
|
||||||
common_unit(get_unit(r1), get_unit(r2), get_unit(rest)...)>{};
|
common_unit(get_unit(R1{}), get_unit(R2{}), get_unit(rest)...)>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
MP_UNITS_EXPORT_END
|
MP_UNITS_EXPORT_END
|
||||||
|
@@ -128,9 +128,10 @@ public:
|
|||||||
MP_UNITS_EXPECTS(detail::is_basic_literal_character_set(a));
|
MP_UNITS_EXPECTS(detail::is_basic_literal_character_set(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr symbol_text(const fixed_u8string<N>& u, const fixed_string<M>& a) : unicode_(u), ascii_(a)
|
constexpr symbol_text(const fixed_u8string<N>& unicode, const fixed_string<M>& ascii) :
|
||||||
|
unicode_(unicode), ascii_(ascii)
|
||||||
{
|
{
|
||||||
MP_UNITS_EXPECTS(detail::is_basic_literal_character_set(a.data_));
|
MP_UNITS_EXPECTS(detail::is_basic_literal_character_set(ascii.data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr const auto& unicode() const { return unicode_; }
|
[[nodiscard]] constexpr const auto& unicode() const { return unicode_; }
|
||||||
|
@@ -220,7 +220,7 @@ struct propagate_point_origin<U, true> {
|
|||||||
template<Magnitude auto M, Unit U>
|
template<Magnitude auto M, Unit U>
|
||||||
struct scaled_unit_impl : detail::unit_interface, detail::propagate_point_origin<U> {
|
struct scaled_unit_impl : detail::unit_interface, detail::propagate_point_origin<U> {
|
||||||
using _base_type_ = scaled_unit_impl; // exposition only
|
using _base_type_ = scaled_unit_impl; // exposition only
|
||||||
static constexpr MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(Magnitude) auto mag = M;
|
static constexpr Magnitude auto mag = M;
|
||||||
static constexpr U reference_unit{};
|
static constexpr U reference_unit{};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -520,9 +520,9 @@ template<typename T, typename F, int Num, int... Den>
|
|||||||
template<typename... Us>
|
template<typename... Us>
|
||||||
[[nodiscard]] consteval auto get_canonical_unit_impl(const type_list<Us...>&)
|
[[nodiscard]] consteval auto get_canonical_unit_impl(const type_list<Us...>&)
|
||||||
{
|
{
|
||||||
auto m = (mp_units::mag<1> * ... * get_canonical_unit_impl(Us{}, Us{}).mag);
|
auto magnitude = (mp_units::mag<1> * ... * get_canonical_unit_impl(Us{}, Us{}).mag);
|
||||||
auto u = (one * ... * get_canonical_unit_impl(Us{}, Us{}).reference_unit);
|
auto u = (one * ... * get_canonical_unit_impl(Us{}, Us{}).reference_unit);
|
||||||
return canonical_unit{m, u};
|
return canonical_unit{magnitude, u};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Unit T, typename... Expr>
|
template<Unit T, typename... Expr>
|
||||||
@@ -632,8 +632,8 @@ template<Unit From, Unit To>
|
|||||||
[[nodiscard]] consteval Unit auto common_unit(Unit auto u) { return u; }
|
[[nodiscard]] consteval Unit auto common_unit(Unit auto u) { return u; }
|
||||||
|
|
||||||
template<Unit U1, Unit U2>
|
template<Unit U1, Unit U2>
|
||||||
|
requires(convertible(U1{}, U2{}))
|
||||||
[[nodiscard]] consteval Unit auto common_unit(U1 u1, U2 u2)
|
[[nodiscard]] consteval Unit auto common_unit(U1 u1, U2 u2)
|
||||||
requires(convertible(u1, u2))
|
|
||||||
{
|
{
|
||||||
if constexpr (is_same_v<U1, U2>)
|
if constexpr (is_same_v<U1, U2>)
|
||||||
return u1;
|
return u1;
|
||||||
@@ -654,8 +654,8 @@ template<Unit U1, Unit U2>
|
|||||||
else if constexpr (is_integral(canonical_rhs.mag / canonical_lhs.mag))
|
else if constexpr (is_integral(canonical_rhs.mag / canonical_lhs.mag))
|
||||||
return u1;
|
return u1;
|
||||||
else {
|
else {
|
||||||
constexpr auto cm = detail::common_magnitude(canonical_lhs.mag, canonical_rhs.mag);
|
constexpr auto common_magnitude = detail::common_magnitude(canonical_lhs.mag, canonical_rhs.mag);
|
||||||
return scaled_unit<cm, decltype(canonical_lhs.reference_unit)>{};
|
return scaled_unit<common_magnitude, decltype(canonical_lhs.reference_unit)>{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -85,13 +85,16 @@ std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<CharT, Traits>&
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename OStream, typename T>
|
||||||
|
constexpr bool is_mp_units_stream = requires(OStream os, T v) { detail::to_stream_impl(os, v); };
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
MP_UNITS_EXPORT_BEGIN
|
MP_UNITS_EXPORT_BEGIN
|
||||||
|
|
||||||
template<typename CharT, typename Traits, typename T>
|
template<typename CharT, typename Traits, typename T>
|
||||||
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const T& v)
|
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const T& v)
|
||||||
requires requires { detail::to_stream_impl(os, v); }
|
requires detail::is_mp_units_stream<std::basic_ostream<CharT, Traits>, T>
|
||||||
{
|
{
|
||||||
return detail::to_stream(os, v);
|
return detail::to_stream(os, v);
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,7 @@ std::vector<typename Q::rep> bl_qty_to_rep(std::initializer_list<Q>& bl)
|
|||||||
template<Quantity Q, typename UnaryOperation>
|
template<Quantity Q, typename UnaryOperation>
|
||||||
std::vector<typename Q::rep> fw_bl_pwc(std::initializer_list<Q>& bl, UnaryOperation fw)
|
std::vector<typename Q::rep> fw_bl_pwc(std::initializer_list<Q>& bl, UnaryOperation fw)
|
||||||
{
|
{
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
std::vector<rep> w_bl;
|
std::vector<rep> w_bl;
|
||||||
w_bl.reserve(bl.size());
|
w_bl.reserve(bl.size());
|
||||||
for (const Q& qty : bl) {
|
for (const Q& qty : bl) {
|
||||||
@@ -93,8 +93,8 @@ MP_UNITS_EXPORT_BEGIN
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::integral<typename Q::rep>
|
requires std::integral<typename Q::rep>
|
||||||
struct uniform_int_distribution : public std::uniform_int_distribution<typename Q::rep> {
|
struct uniform_int_distribution : public std::uniform_int_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::uniform_int_distribution<rep>;
|
using base = std::uniform_int_distribution<rep>;
|
||||||
|
|
||||||
uniform_int_distribution() : base() {}
|
uniform_int_distribution() : base() {}
|
||||||
uniform_int_distribution(const Q& a, const Q& b) :
|
uniform_int_distribution(const Q& a, const Q& b) :
|
||||||
@@ -118,8 +118,8 @@ struct uniform_int_distribution : public std::uniform_int_distribution<typename
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct uniform_real_distribution : public std::uniform_real_distribution<typename Q::rep> {
|
struct uniform_real_distribution : public std::uniform_real_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::uniform_real_distribution<rep>;
|
using base = std::uniform_real_distribution<rep>;
|
||||||
|
|
||||||
uniform_real_distribution() : base() {}
|
uniform_real_distribution() : base() {}
|
||||||
uniform_real_distribution(const Q& a, const Q& b) :
|
uniform_real_distribution(const Q& a, const Q& b) :
|
||||||
@@ -143,8 +143,8 @@ struct uniform_real_distribution : public std::uniform_real_distribution<typenam
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::integral<typename Q::rep>
|
requires std::integral<typename Q::rep>
|
||||||
struct binomial_distribution : public std::binomial_distribution<typename Q::rep> {
|
struct binomial_distribution : public std::binomial_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::binomial_distribution<rep>;
|
using base = std::binomial_distribution<rep>;
|
||||||
|
|
||||||
binomial_distribution() : base() {}
|
binomial_distribution() : base() {}
|
||||||
binomial_distribution(const Q& t, double p) : base(t.numerical_value_ref_in(Q::unit), p) {}
|
binomial_distribution(const Q& t, double p) : base(t.numerical_value_ref_in(Q::unit), p) {}
|
||||||
@@ -164,8 +164,8 @@ struct binomial_distribution : public std::binomial_distribution<typename Q::rep
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::integral<typename Q::rep>
|
requires std::integral<typename Q::rep>
|
||||||
struct negative_binomial_distribution : public std::negative_binomial_distribution<typename Q::rep> {
|
struct negative_binomial_distribution : public std::negative_binomial_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::negative_binomial_distribution<rep>;
|
using base = std::negative_binomial_distribution<rep>;
|
||||||
|
|
||||||
negative_binomial_distribution() : base() {}
|
negative_binomial_distribution() : base() {}
|
||||||
negative_binomial_distribution(const Q& k, double p) : base(k.numerical_value_ref_in(Q::unit), p) {}
|
negative_binomial_distribution(const Q& k, double p) : base(k.numerical_value_ref_in(Q::unit), p) {}
|
||||||
@@ -185,8 +185,8 @@ struct negative_binomial_distribution : public std::negative_binomial_distributi
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::integral<typename Q::rep>
|
requires std::integral<typename Q::rep>
|
||||||
struct geometric_distribution : public std::geometric_distribution<typename Q::rep> {
|
struct geometric_distribution : public std::geometric_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::geometric_distribution<rep>;
|
using base = std::geometric_distribution<rep>;
|
||||||
|
|
||||||
geometric_distribution() : base() {}
|
geometric_distribution() : base() {}
|
||||||
explicit geometric_distribution(double p) : base(p) {}
|
explicit geometric_distribution(double p) : base(p) {}
|
||||||
@@ -204,8 +204,8 @@ struct geometric_distribution : public std::geometric_distribution<typename Q::r
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::integral<typename Q::rep>
|
requires std::integral<typename Q::rep>
|
||||||
struct poisson_distribution : public std::poisson_distribution<typename Q::rep> {
|
struct poisson_distribution : public std::poisson_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::poisson_distribution<rep>;
|
using base = std::poisson_distribution<rep>;
|
||||||
|
|
||||||
poisson_distribution() : base() {}
|
poisson_distribution() : base() {}
|
||||||
explicit poisson_distribution(double p) : base(p) {}
|
explicit poisson_distribution(double p) : base(p) {}
|
||||||
@@ -223,8 +223,8 @@ struct poisson_distribution : public std::poisson_distribution<typename Q::rep>
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct exponential_distribution : public std::exponential_distribution<typename Q::rep> {
|
struct exponential_distribution : public std::exponential_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::exponential_distribution<rep>;
|
using base = std::exponential_distribution<rep>;
|
||||||
|
|
||||||
exponential_distribution() : base() {}
|
exponential_distribution() : base() {}
|
||||||
explicit exponential_distribution(const rep& lambda) : base(lambda) {}
|
explicit exponential_distribution(const rep& lambda) : base(lambda) {}
|
||||||
@@ -242,8 +242,8 @@ struct exponential_distribution : public std::exponential_distribution<typename
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct gamma_distribution : public std::gamma_distribution<typename Q::rep> {
|
struct gamma_distribution : public std::gamma_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::gamma_distribution<rep>;
|
using base = std::gamma_distribution<rep>;
|
||||||
|
|
||||||
gamma_distribution() : base() {}
|
gamma_distribution() : base() {}
|
||||||
gamma_distribution(const rep& alpha, const rep& beta) : base(alpha, beta) {}
|
gamma_distribution(const rep& alpha, const rep& beta) : base(alpha, beta) {}
|
||||||
@@ -261,8 +261,8 @@ struct gamma_distribution : public std::gamma_distribution<typename Q::rep> {
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct weibull_distribution : public std::weibull_distribution<typename Q::rep> {
|
struct weibull_distribution : public std::weibull_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::weibull_distribution<rep>;
|
using base = std::weibull_distribution<rep>;
|
||||||
|
|
||||||
weibull_distribution() : base() {}
|
weibull_distribution() : base() {}
|
||||||
weibull_distribution(const rep& a, const rep& b) : base(a, b) {}
|
weibull_distribution(const rep& a, const rep& b) : base(a, b) {}
|
||||||
@@ -280,8 +280,8 @@ struct weibull_distribution : public std::weibull_distribution<typename Q::rep>
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct extreme_value_distribution : public std::extreme_value_distribution<typename Q::rep> {
|
struct extreme_value_distribution : public std::extreme_value_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::extreme_value_distribution<rep>;
|
using base = std::extreme_value_distribution<rep>;
|
||||||
|
|
||||||
extreme_value_distribution() : base() {}
|
extreme_value_distribution() : base() {}
|
||||||
extreme_value_distribution(const Q& a, const rep& b) : base(a.numerical_value_ref_in(Q::unit), b) {}
|
extreme_value_distribution(const Q& a, const rep& b) : base(a.numerical_value_ref_in(Q::unit), b) {}
|
||||||
@@ -301,8 +301,8 @@ struct extreme_value_distribution : public std::extreme_value_distribution<typen
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct normal_distribution : public std::normal_distribution<typename Q::rep> {
|
struct normal_distribution : public std::normal_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::normal_distribution<rep>;
|
using base = std::normal_distribution<rep>;
|
||||||
|
|
||||||
normal_distribution() : base() {}
|
normal_distribution() : base() {}
|
||||||
normal_distribution(const Q& mean, const Q& stddev) :
|
normal_distribution(const Q& mean, const Q& stddev) :
|
||||||
@@ -326,8 +326,8 @@ struct normal_distribution : public std::normal_distribution<typename Q::rep> {
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct lognormal_distribution : public std::lognormal_distribution<typename Q::rep> {
|
struct lognormal_distribution : public std::lognormal_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::lognormal_distribution<rep>;
|
using base = std::lognormal_distribution<rep>;
|
||||||
|
|
||||||
lognormal_distribution() : base() {}
|
lognormal_distribution() : base() {}
|
||||||
lognormal_distribution(const Q& m, const Q& s) :
|
lognormal_distribution(const Q& m, const Q& s) :
|
||||||
@@ -351,8 +351,8 @@ struct lognormal_distribution : public std::lognormal_distribution<typename Q::r
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct chi_squared_distribution : public std::chi_squared_distribution<typename Q::rep> {
|
struct chi_squared_distribution : public std::chi_squared_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::chi_squared_distribution<rep>;
|
using base = std::chi_squared_distribution<rep>;
|
||||||
|
|
||||||
chi_squared_distribution() : base() {}
|
chi_squared_distribution() : base() {}
|
||||||
explicit chi_squared_distribution(const rep& n) : base(n) {}
|
explicit chi_squared_distribution(const rep& n) : base(n) {}
|
||||||
@@ -370,8 +370,8 @@ struct chi_squared_distribution : public std::chi_squared_distribution<typename
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct cauchy_distribution : public std::cauchy_distribution<typename Q::rep> {
|
struct cauchy_distribution : public std::cauchy_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::cauchy_distribution<rep>;
|
using base = std::cauchy_distribution<rep>;
|
||||||
|
|
||||||
cauchy_distribution() : base() {}
|
cauchy_distribution() : base() {}
|
||||||
cauchy_distribution(const Q& a, const Q& b) :
|
cauchy_distribution(const Q& a, const Q& b) :
|
||||||
@@ -395,8 +395,8 @@ struct cauchy_distribution : public std::cauchy_distribution<typename Q::rep> {
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct fisher_f_distribution : public std::fisher_f_distribution<typename Q::rep> {
|
struct fisher_f_distribution : public std::fisher_f_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::fisher_f_distribution<rep>;
|
using base = std::fisher_f_distribution<rep>;
|
||||||
|
|
||||||
fisher_f_distribution() : base() {}
|
fisher_f_distribution() : base() {}
|
||||||
fisher_f_distribution(const rep& m, const rep& n) : base(m, n) {}
|
fisher_f_distribution(const rep& m, const rep& n) : base(m, n) {}
|
||||||
@@ -414,8 +414,8 @@ struct fisher_f_distribution : public std::fisher_f_distribution<typename Q::rep
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
struct student_t_distribution : public std::student_t_distribution<typename Q::rep> {
|
struct student_t_distribution : public std::student_t_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::student_t_distribution<rep>;
|
using base = std::student_t_distribution<rep>;
|
||||||
|
|
||||||
student_t_distribution() : base() {}
|
student_t_distribution() : base() {}
|
||||||
explicit student_t_distribution(const rep& n) : base(n) {}
|
explicit student_t_distribution(const rep& n) : base(n) {}
|
||||||
@@ -433,8 +433,8 @@ struct student_t_distribution : public std::student_t_distribution<typename Q::r
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::integral<typename Q::rep>
|
requires std::integral<typename Q::rep>
|
||||||
struct discrete_distribution : public std::discrete_distribution<typename Q::rep> {
|
struct discrete_distribution : public std::discrete_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::discrete_distribution<rep>;
|
using base = std::discrete_distribution<rep>;
|
||||||
|
|
||||||
discrete_distribution() : base() {}
|
discrete_distribution() : base() {}
|
||||||
|
|
||||||
@@ -464,8 +464,8 @@ struct discrete_distribution : public std::discrete_distribution<typename Q::rep
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
class piecewise_constant_distribution : public std::piecewise_constant_distribution<typename Q::rep> {
|
class piecewise_constant_distribution : public std::piecewise_constant_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::piecewise_constant_distribution<rep>;
|
using base = std::piecewise_constant_distribution<rep>;
|
||||||
|
|
||||||
template<typename InputIt>
|
template<typename InputIt>
|
||||||
piecewise_constant_distribution(const std::vector<rep>& i, InputIt first_w) : base(i.cbegin(), i.cend(), first_w)
|
piecewise_constant_distribution(const std::vector<rep>& i, InputIt first_w) : base(i.cbegin(), i.cend(), first_w)
|
||||||
@@ -523,8 +523,8 @@ public:
|
|||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires std::floating_point<typename Q::rep>
|
requires std::floating_point<typename Q::rep>
|
||||||
class piecewise_linear_distribution : public std::piecewise_linear_distribution<typename Q::rep> {
|
class piecewise_linear_distribution : public std::piecewise_linear_distribution<typename Q::rep> {
|
||||||
using rep = MP_UNITS_TYPENAME Q::rep;
|
using rep = Q::rep;
|
||||||
using base = MP_UNITS_TYPENAME std::piecewise_linear_distribution<rep>;
|
using base = std::piecewise_linear_distribution<rep>;
|
||||||
|
|
||||||
template<typename InputIt>
|
template<typename InputIt>
|
||||||
piecewise_linear_distribution(const std::vector<rep>& i, InputIt first_w) : base(i.cbegin(), i.cend(), first_w)
|
piecewise_linear_distribution(const std::vector<rep>& i, InputIt first_w) : base(i.cbegin(), i.cend(), first_w)
|
||||||
|
@@ -127,18 +127,18 @@ namespace detail {
|
|||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template<QuantityOf<isq::time> Q>
|
template<QuantityOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::time)> Q>
|
||||||
[[nodiscard]] constexpr auto to_chrono_duration(const Q& q)
|
[[nodiscard]] constexpr auto to_chrono_duration(const Q& q)
|
||||||
{
|
{
|
||||||
return std::chrono::duration<typename Q::rep, decltype(detail::as_ratio(get_canonical_unit(Q::unit).mag))>{q};
|
return std::chrono::duration<typename Q::rep, decltype(detail::as_ratio(get_canonical_unit(Q::unit).mag))>{q};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPointOf<isq::time> QP>
|
template<QuantityPointOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::time)> QP>
|
||||||
requires is_specialization_of<std::remove_const_t<decltype(QP::absolute_point_origin)>, chrono_point_origin_>
|
requires is_specialization_of<std::remove_const_t<decltype(QP::absolute_point_origin)>, chrono_point_origin_>
|
||||||
[[nodiscard]] constexpr auto to_chrono_time_point(const QP& qp)
|
[[nodiscard]] constexpr auto to_chrono_time_point(const QP& qp)
|
||||||
{
|
{
|
||||||
using clock = MP_UNITS_TYPENAME decltype(QP::absolute_point_origin)::clock;
|
using clock = decltype(QP::absolute_point_origin)::clock;
|
||||||
using rep = MP_UNITS_TYPENAME QP::rep;
|
using rep = QP::rep;
|
||||||
using ret_type =
|
using ret_type =
|
||||||
std::chrono::time_point<clock,
|
std::chrono::time_point<clock,
|
||||||
std::chrono::duration<rep, decltype(detail::as_ratio(get_canonical_unit(QP::unit).mag))>>;
|
std::chrono::duration<rep, decltype(detail::as_ratio(get_canonical_unit(QP::unit).mag))>>;
|
||||||
|
@@ -43,7 +43,7 @@ import std;
|
|||||||
|
|
||||||
MP_UNITS_EXPORT
|
MP_UNITS_EXPORT
|
||||||
namespace mp_units::si {
|
namespace mp_units::si {
|
||||||
template<ReferenceOf<isq::angular_measure> auto R, typename Rep>
|
template<ReferenceOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::angular_measure)> auto R, typename Rep>
|
||||||
requires requires(Rep v) { sin(v); } || requires(Rep v) { std::sin(v); }
|
requires requires(Rep v) { sin(v); } || requires(Rep v) { std::sin(v); }
|
||||||
[[nodiscard]] inline QuantityOf<dimensionless> auto sin(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<dimensionless> auto sin(const quantity<R, Rep>& q) noexcept
|
||||||
{
|
{
|
||||||
@@ -57,7 +57,7 @@ template<ReferenceOf<isq::angular_measure> auto R, typename Rep>
|
|||||||
return quantity{sin(q.numerical_value_in(radian)), one};
|
return quantity{sin(q.numerical_value_in(radian)), one};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<ReferenceOf<isq::angular_measure> auto R, typename Rep>
|
template<ReferenceOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::angular_measure)> auto R, typename Rep>
|
||||||
requires requires(Rep v) { cos(v); } || requires(Rep v) { std::cos(v); }
|
requires requires(Rep v) { cos(v); } || requires(Rep v) { std::cos(v); }
|
||||||
[[nodiscard]] inline QuantityOf<dimensionless> auto cos(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<dimensionless> auto cos(const quantity<R, Rep>& q) noexcept
|
||||||
{
|
{
|
||||||
@@ -71,7 +71,7 @@ template<ReferenceOf<isq::angular_measure> auto R, typename Rep>
|
|||||||
return quantity{cos(q.numerical_value_in(radian)), one};
|
return quantity{cos(q.numerical_value_in(radian)), one};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<ReferenceOf<isq::angular_measure> auto R, typename Rep>
|
template<ReferenceOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::angular_measure)> auto R, typename Rep>
|
||||||
requires requires(Rep v) { tan(v); } || requires(Rep v) { std::tan(v); }
|
requires requires(Rep v) { tan(v); } || requires(Rep v) { std::tan(v); }
|
||||||
[[nodiscard]] inline QuantityOf<dimensionless> auto tan(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<dimensionless> auto tan(const quantity<R, Rep>& q) noexcept
|
||||||
{
|
{
|
||||||
@@ -87,7 +87,8 @@ template<ReferenceOf<isq::angular_measure> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
||||||
requires requires(Rep v) { asin(v); } || requires(Rep v) { std::asin(v); }
|
requires requires(Rep v) { asin(v); } || requires(Rep v) { std::asin(v); }
|
||||||
[[nodiscard]] inline QuantityOf<isq::angular_measure> auto asin(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::angular_measure)> auto asin(
|
||||||
|
const quantity<R, Rep>& q) noexcept
|
||||||
{
|
{
|
||||||
using std::asin;
|
using std::asin;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
@@ -101,7 +102,8 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
||||||
requires requires(Rep v) { acos(v); } || requires(Rep v) { std::acos(v); }
|
requires requires(Rep v) { acos(v); } || requires(Rep v) { std::acos(v); }
|
||||||
[[nodiscard]] inline QuantityOf<isq::angular_measure> auto acos(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::angular_measure)> auto acos(
|
||||||
|
const quantity<R, Rep>& q) noexcept
|
||||||
{
|
{
|
||||||
using std::acos;
|
using std::acos;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
@@ -115,7 +117,8 @@ template<ReferenceOf<dimensionless> auto R, typename Rep>
|
|||||||
|
|
||||||
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
template<ReferenceOf<dimensionless> auto R, typename Rep>
|
||||||
requires requires(Rep v) { atan(v); } || requires(Rep v) { std::atan(v); }
|
requires requires(Rep v) { atan(v); } || requires(Rep v) { std::atan(v); }
|
||||||
[[nodiscard]] inline QuantityOf<isq::angular_measure> auto atan(const quantity<R, Rep>& q) noexcept
|
[[nodiscard]] inline QuantityOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::angular_measure)> auto atan(
|
||||||
|
const quantity<R, Rep>& q) noexcept
|
||||||
{
|
{
|
||||||
using std::atan;
|
using std::atan;
|
||||||
if constexpr (!treat_as_floating_point<Rep>) {
|
if constexpr (!treat_as_floating_point<Rep>) {
|
||||||
@@ -132,8 +135,8 @@ template<auto R1, typename Rep1, auto R2, typename Rep2>
|
|||||||
common_reference(R1, R2);
|
common_reference(R1, R2);
|
||||||
requires requires { atan2(v1, v2); } || requires { std::atan2(v1, v2); };
|
requires requires { atan2(v1, v2); } || requires { std::atan2(v1, v2); };
|
||||||
}
|
}
|
||||||
[[nodiscard]] inline QuantityOf<isq::angular_measure> auto atan2(const quantity<R1, Rep1>& y,
|
[[nodiscard]] inline QuantityOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::angular_measure)> auto atan2(
|
||||||
const quantity<R2, Rep2>& x) noexcept
|
const quantity<R1, Rep1>& y, const quantity<R2, Rep2>& x) noexcept
|
||||||
{
|
{
|
||||||
constexpr auto ref = common_reference(R1, R2);
|
constexpr auto ref = common_reference(R1, R2);
|
||||||
constexpr auto unit = get_unit(ref);
|
constexpr auto unit = get_unit(ref);
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
|
#include <mp-units/bits/hacks.h>
|
||||||
#include <mp-units/format.h>
|
#include <mp-units/format.h>
|
||||||
#include <mp-units/ostream.h>
|
#include <mp-units/ostream.h>
|
||||||
#include <mp-units/systems/isq.h>
|
#include <mp-units/systems/isq.h>
|
||||||
@@ -28,7 +29,8 @@
|
|||||||
|
|
||||||
using namespace mp_units;
|
using namespace mp_units;
|
||||||
|
|
||||||
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::distance> auto d, QuantityOf<isq::duration> auto t)
|
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::distance)> auto d,
|
||||||
|
QuantityOf<MP_UNITS_IS_VALUE_WORKAROUND(isq::duration)> auto t)
|
||||||
{
|
{
|
||||||
return d / t;
|
return d / t;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user