refactor: underlying_type split to wrapped_type and value_type and used in code

This commit is contained in:
Mateusz Pusz
2024-04-25 16:08:23 +02:00
parent 4e339cdcd8
commit 56bfe8f011
4 changed files with 28 additions and 27 deletions

View File

@@ -70,12 +70,12 @@ template<Quantity To, typename From>
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>;
using multiplier_type = conditional<treat_as_floating_point<c_rep_type>,
using multiplier_type = conditional<
treat_as_floating_point<c_rep_type>,
// ensure that the multiplier is also floating-point
conditional<std::is_arithmetic_v<underlying_type_t<c_rep_type>>,
conditional<std::is_arithmetic_v<value_type_t<c_rep_type>>,
// reuse user's type if possible
std::common_type_t<c_mag_type, underlying_type_t<c_rep_type>>,
std::common_type_t<c_mag_type, double>>,
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>;
constexpr auto val = [](Magnitude auto m) { return get_value<multiplier_type>(m); };

View File

@@ -106,20 +106,30 @@ struct get_element_type {
} // namespace detail
template<typename T>
struct underlying_type {
using type = T;
};
template<typename T>
requires requires { typename T::value_type; } || requires { typename T::element_type; }
struct underlying_type<T> {
struct wrapped_type {
using type = MP_UNITS_TYPENAME
conditional<requires { typename T::value_type; }, detail::get_value_type<T>, detail::get_element_type<T>>::type;
};
template<typename T>
using underlying_type_t = MP_UNITS_TYPENAME underlying_type<T>::type;
requires requires { typename T::value_type; } || requires { typename T::element_type; }
using wrapped_type_t = MP_UNITS_TYPENAME wrapped_type<T>::type;
template<typename T>
struct value_type {
using type = T;
};
template<typename T>
requires requires { typename wrapped_type_t<T>; }
struct value_type<T> {
using type = MP_UNITS_TYPENAME wrapped_type_t<T>;
};
template<typename T>
using value_type_t = MP_UNITS_TYPENAME value_type<T>::type;
template<typename T, typename... Ts>
concept one_of = (false || ... || std::same_as<T, Ts>);

View File

@@ -48,14 +48,8 @@ template<typename Rep>
inline constexpr bool treat_as_floating_point = std::is_floating_point_v<Rep>;
template<typename Rep>
requires requires { typename Rep::value_type; } || requires { typename Rep::element_type; }
inline constexpr bool treat_as_floating_point<Rep> = requires {
typename Rep::value_type;
requires treat_as_floating_point<typename Rep::value_type>;
} || requires {
typename Rep::element_type;
requires treat_as_floating_point<std::remove_reference_t<typename Rep::element_type>>;
};
requires requires { typename wrapped_type_t<Rep>; }
inline constexpr bool treat_as_floating_point<Rep> = treat_as_floating_point<wrapped_type_t<Rep>>;
/**
* @brief Specifies a type to have a scalar character

View File

@@ -72,11 +72,8 @@ concept CastableNumber = CommonTypeWith<T, std::intmax_t> && ScalableNumber<std:
// TODO Fix it according to sudo_cast implementation
template<typename T>
concept Scalable =
CastableNumber<T> ||
(requires { typename T::value_type; } && CastableNumber<typename T::value_type> &&
ScalableNumber<T, std::common_type_t<typename T::value_type, std::intmax_t>>) ||
(requires { typename T::element_type; } && CastableNumber<std::remove_reference_t<typename T::element_type>> &&
ScalableNumber<T, std::common_type_t<std::remove_reference_t<typename T::element_type>, std::intmax_t>>);
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>>);
} // namespace detail