refactor: interoperability with quantity-like types simplified

Type trait specialization for each `quantity` type is not needed anymore.

Relates to #33.
This commit is contained in:
Mateusz Pusz committed 2020-10-07 14:29:12 +02:00
1 parent 2dd8c90250
commit d64d26a4c4
9 files changed
+66 -78

No files matched your search

+16 -17
View File
@@ -36,8 +36,8 @@ namespace units {
template<typename T>
concept floating_point_ = // exposition only
(QuantityLike<T> && treat_as_floating_point<typename quantity_traits<T>::rep>) ||
(!QuantityLike<T> && treat_as_floating_point<T>);
(Quantity<T> && treat_as_floating_point<typename T::rep>) ||
(!Quantity<T> && treat_as_floating_point<T>);
template<typename From, typename To>
concept safe_convertible_to_ = // exposition only
@@ -49,15 +49,15 @@ concept safe_convertible_to_ = // exposition only
// QFrom ratio is an exact multiple of QTo
template<typename QFrom, typename QTo>
concept harmonic_ = // exposition only
QuantityLike<QFrom> &&
Quantity<QFrom> &&
Quantity<QTo> &&
requires(QFrom from, QTo to) { requires is_integral(detail::quantity_ratio(from) / detail::quantity_ratio(to)); };
template<typename QFrom, typename QTo>
concept safe_castable_to_ = // exposition only
QuantityLike<QFrom> &&
QuantityOf<QTo, typename quantity_traits<QFrom>::dimension> &&
scalable_with_<typename quantity_traits<QFrom>::rep, typename QTo::rep> &&
Quantity<QFrom> &&
QuantityOf<QTo, typename QFrom::dimension> &&
scalable_with_<typename QFrom::rep, typename QTo::rep> &&
(floating_point_<QTo> || (!floating_point_<QFrom> && harmonic_<QFrom, QTo>));
template<typename Func, typename T, typename U>
@@ -81,6 +81,9 @@ template<typename Func, Quantity Q1, QuantityEquivalentTo<Q1> Q2>
requires quantity_value_for_<Func, typename Q1::rep, typename Q2::rep>
using common_quantity_for = common_quantity<Q1, Q2, std::invoke_result_t<Func, typename Q1::rep, typename Q2::rep>>;
template<QuantityLike Q>
using quantity_like_type = quantity<typename quantity_like_traits<Q>::dimension, typename quantity_like_traits<Q>::unit, typename quantity_like_traits<Q>::rep>;
/**
* @brief A quantity
*
@@ -133,8 +136,12 @@ public:
template<safe_convertible_to_<rep> Value>
explicit(!(equivalent<quantity, dimensionless<::units::one, rep>>)) constexpr quantity(const Value& v) : value_(static_cast<rep>(v)) {}
template<QuantityLike Q>
requires std::same_as<quantity, quantity_like_type<Q>>
explicit constexpr quantity(const Q& q) : value_(q.count()) {}
template<safe_castable_to_<quantity> Q>
explicit(!Quantity<Q>) constexpr quantity(const Q& q) : value_(quantity_cast<quantity>(q).count()) {}
constexpr quantity(const Q& q) : value_(quantity_cast<quantity>(q).count()) {}
quantity& operator=(const quantity&) = default;
quantity& operator=(quantity&&) = default;
@@ -328,10 +335,10 @@ template<QuantityValue V>
explicit(false) quantity(V) -> quantity<dim_one, one, V>;
template<QuantityLike Q>
explicit(!Quantity<Q>) quantity(Q) -> quantity<typename quantity_traits<Q>::dimension, typename quantity_traits<Q>::unit, typename quantity_traits<Q>::rep>;
explicit quantity(Q) -> quantity_like_type<Q>;
// non-member binary operators
template<QuantityLike Q1, QuantityEquivalentTo<Q1> Q2>
template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
requires quantity_value_for_<std::plus<>, typename Q1::rep, typename Q2::rep>
[[nodiscard]] constexpr Quantity auto operator+(const Q1& lhs, const Q2& rhs)
{
@@ -404,14 +411,6 @@ template<Quantity Q1, QuantityEquivalentTo<Q1> Q2>
}
// type traits
template<typename D, typename U, typename Rep>
struct quantity_traits<quantity<D, U, Rep>> {
using dimension = D;
using unit = U;
using rep = Rep;
static constexpr rep count(const quantity<D, U, Rep>& q) { return q.count(); }
};
namespace detail {
template<typename D, typename U, typename Rep>