refactor: std::common_type usage replaced with dedicated functions for units, dimensions, and references

This commit is contained in:
Mateusz Pusz
2022-11-09 18:39:51 -10:00
parent 649252d691
commit f2e63fdeb1
6 changed files with 74 additions and 97 deletions
+10 -19
View File
@@ -386,31 +386,22 @@ template<Unit auto U, Dimension auto Dim>
requires requires { detail::get_dimension_for(U); } && (interconvertible(Dim, detail::get_dimension_for(U)))
inline constexpr bool is_valid_unit_for_dimension<U, Dim> = true;
} // namespace detail
template<Dimension D1, Dimension D2>
[[nodiscard]] consteval auto common_dimension(D1 d1, D2 d2)
requires(interconvertible(d1, d2))
{
if constexpr (std::derived_from<D1, D2>)
return d1;
else
return d2;
}
} // namespace detail
// TODO consider adding the support for text output of the dimensional equation
} // namespace units
namespace std {
/**
* @brief Partial specialization of `std::common_type` for dimensions
*
* Defined only for convertible types and returns the most derived/specific dimension type of
* the two provided.
*/
template<units::Dimension D1, units::Dimension D2>
requires(units::interconvertible(D1{}, D2{}))
struct common_type<D1, D2> {
using type = ::units::conditional<std::derived_from<std::remove_const_t<D1>, std::remove_const_t<D2>>,
std::remove_const_t<D1>, std::remove_const_t<D2>>;
};
} // namespace std
#ifdef __cpp_explicit_this_parameter
#define BASE_DIMENSION(name, symbol) \
+13 -12
View File
@@ -474,8 +474,8 @@ template<Quantity Q1, Quantity Q2>
quantity_value_for_<std::plus<>, typename Q1::rep, typename Q2::rep>
[[nodiscard]] constexpr Quantity auto operator+(const Q1& lhs, const Q2& rhs)
{
using ref = std::common_type_t<decltype(Q1::reference), decltype(Q2::reference)>;
using ret = quantity<ref{}, decltype(lhs.number() + rhs.number())>;
constexpr auto ref = detail::common_reference(Q1::reference, Q2::reference);
using ret = quantity<ref, decltype(lhs.number() + rhs.number())>;
return ret(ret(lhs).number() + ret(rhs).number());
}
@@ -484,8 +484,8 @@ template<Quantity Q1, Quantity Q2>
quantity_value_for_<std::minus<>, typename Q1::rep, typename Q2::rep>
[[nodiscard]] constexpr Quantity auto operator-(const Q1& lhs, const Q2& rhs)
{
using ref = std::common_type_t<decltype(Q1::reference), decltype(Q2::reference)>;
using ret = quantity<ref{}, decltype(lhs.number() - rhs.number())>;
constexpr auto ref = detail::common_reference(Q1::reference, Q2::reference);
using ret = quantity<ref, decltype(lhs.number() - rhs.number())>;
return ret(ret(lhs).number() - ret(rhs).number());
}
@@ -521,8 +521,8 @@ template<Quantity Q1, Quantity Q2>
std::three_way_comparable_with<typename Q1::rep, typename Q2::rep>
[[nodiscard]] constexpr auto operator<=>(const Q1& lhs, const Q2& rhs)
{
using ref = std::common_type_t<decltype(Q1::reference), decltype(Q2::reference)>;
return quantity_cast<ref{}>(lhs).number() <=> quantity_cast<ref{}>(rhs).number();
constexpr auto ref = detail::common_reference(Q1::reference, Q2::reference);
return quantity_cast<ref>(lhs).number() <=> quantity_cast<ref>(rhs).number();
}
template<Quantity Q1, Quantity Q2>
@@ -530,8 +530,8 @@ template<Quantity Q1, Quantity Q2>
std::equality_comparable_with<typename Q1::rep, typename Q2::rep>
[[nodiscard]] constexpr bool operator==(const Q1& lhs, const Q2& rhs)
{
using ref = std::common_type_t<decltype(Q1::reference), decltype(Q2::reference)>;
return quantity_cast<ref{}>(lhs).number() == quantity_cast<ref{}>(rhs).number();
constexpr auto ref = detail::common_reference(Q1::reference, Q2::reference);
return quantity_cast<ref>(lhs).number() == quantity_cast<ref>(rhs).number();
}
} // namespace units
@@ -540,14 +540,15 @@ namespace std {
template<units::Quantity Q1, units::Quantity Q2>
requires requires {
typename common_type_t<remove_const_t<decltype(Q1::reference)>, remove_const_t<decltype(Q2::reference)>>;
{
units::detail::common_reference(Q1::reference, Q2::reference)
} -> units::Reference;
typename common_type_t<typename Q1::rep, typename Q2::rep>;
}
struct common_type<Q1, Q2> {
private:
using ref = common_type_t<remove_const_t<decltype(Q1::reference)>, remove_const_t<decltype(Q2::reference)>>;
public:
using type = units::quantity<ref{}, common_type_t<typename Q1::rep, typename Q2::rep>>;
using type = units::quantity<units::detail::common_reference(Q1::reference, Q2::reference),
common_type_t<typename Q1::rep, typename Q2::rep>>;
};
} // namespace std
+13 -14
View File
@@ -107,21 +107,20 @@ template<Reference R1, Reference R2>
return interconvertible(R1::dimension, R2::dimension) && interconvertible(R1::unit, R2::unit);
}
} // namespace units
namespace detail {
namespace std {
template<units::Reference R1, units::Reference R2>
[[nodiscard]] consteval auto common_reference(Reference auto r1, Reference auto r2)
requires requires {
typename common_type_t<remove_const_t<decltype(R1::dimension)>, remove_const_t<decltype(R2::dimension)>>;
typename common_type_t<remove_const_t<decltype(R1::unit)>, remove_const_t<decltype(R2::unit)>>;
{
common_dimension(r1.dimension, r2.dimension)
} -> Dimension;
{
common_unit(r1.unit, r2.unit)
} -> Unit;
}
struct common_type<R1, R2> {
private:
using dim = common_type_t<remove_const_t<decltype(R1::dimension)>, remove_const_t<decltype(R2::dimension)>>;
using unit = common_type_t<remove_const_t<decltype(R1::unit)>, remove_const_t<decltype(R2::unit)>>;
public:
using type = units::reference<dim{}, unit{}>;
};
{
return reference<common_dimension(r1.dimension, r2.dimension), common_unit(r1.unit, r2.unit)>{};
}
} // namespace std
} // namespace detail
} // namespace units
+3 -14
View File
@@ -796,9 +796,9 @@ template<typename CharT = char, Unit U>
namespace detail {
template<typename U1, typename U2>
[[nodiscard]] consteval auto common_type_impl(const U1 u1, const U2 u2)
template<Unit U1, Unit U2>
[[nodiscard]] consteval auto common_unit(U1 u1, U2 u2)
requires(interconvertible(u1, u2))
{
if constexpr (U1{} == U2{}) {
if constexpr (std::derived_from<U1, U2>)
@@ -821,15 +821,4 @@ template<typename U1, typename U2>
}
} // namespace detail
} // namespace units
namespace std {
template<units::Unit U1, units::Unit U2>
requires(units::interconvertible(U1{}, U2{}))
struct common_type<U1, U2> {
using type = std::remove_const_t<decltype(::units::detail::common_type_impl(U1{}, U2{}))>;
};
} // namespace std