diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index bfaae45f..25dcfdfa 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -48,6 +48,23 @@ namespace units { template concept bool Quantity = detail::is_quantity; + // common_quantity + template + struct common_quantity; + + template + struct common_quantity, quantity, Rep> { + using type = quantity; + }; + + template + struct common_quantity, quantity, Rep> { + using type = quantity>>, Rep>; + }; + + template> + using common_quantity_t = typename common_quantity::type; + // treat_as_floating_point template // todo Conceptify that @@ -217,7 +234,8 @@ namespace units { [[nodiscard]] constexpr Quantity operator+(const quantity& lhs, const quantity& rhs) { - using ret = std::common_type_t, quantity>; + using common_rep = decltype(lhs.count() + rhs.count()); + using ret = common_quantity_t, quantity, common_rep>; return ret(ret(lhs).count() + ret(rhs).count()); } @@ -225,58 +243,66 @@ namespace units { [[nodiscard]] constexpr Quantity operator-(const quantity& lhs, const quantity& rhs) { - using ret = std::common_type_t, quantity>; + using common_rep = decltype(lhs.count() - rhs.count()); + using ret = common_quantity_t, quantity, common_rep>; return ret(ret(lhs).count() - ret(rhs).count()); } - template - [[nodiscard]] quantity> - constexpr operator*(const quantity& q, - const Rep2& v) +// template + template + requires !Quantity + /* [[nodiscard]]*/ constexpr Quantity operator*(const quantity& q, + const Rep2& v) { - using ret = quantity>; + using common_rep = decltype(q.count()* v); + using ret = quantity; return ret(ret(q).count() * v); } - template - [[nodiscard]] quantity> - constexpr operator*(const Rep1& v, - const quantity& q) + //template + template + requires !Quantity + /* [[nodiscard]]*/ constexpr Quantity operator*(const Rep1& v, + const quantity& q) { return q * v; } template - requires treat_as_floating_point> || (std::ratio_multiply::den == 1) - /* [[nodiscard]] */ constexpr Quantity operator*(const quantity& lhs, + [[nodiscard]] constexpr Quantity operator*(const quantity& lhs, const quantity& rhs) + requires treat_as_floating_point || + (std::ratio_multiply::den == 1) { using dim = dimension_multiply_t; - using ret = quantity>>, std::common_type_t>; + using common_rep = decltype(lhs.count() * rhs.count()); + using ret = quantity>>, common_rep>; return ret(lhs.count() * rhs.count()); } - template - [[nodiscard]] quantity, upcasting_traits_t, std::ratio>>, std::common_type_t> - constexpr operator/(const Rep1& v, - const quantity& q) +// template + template + [[nodiscard]] constexpr Quantity operator/(const Rep1& v, + const quantity& q) { Expects(q != std::decay_t(0)); using dim = dim_invert_t; - using ret = quantity>>, std::common_type_t>; - using den = quantity>; + using common_rep = decltype(v / q.count()); + using ret = quantity>>, common_rep>; + using den = quantity; return ret(v / den(q).count()); } - template - [[nodiscard]] quantity> - constexpr operator/(const quantity& q, - const Rep2& v) +// template + template + [[nodiscard]] constexpr Quantity operator/(const quantity& q, + const Rep2& v) { Expects(v != Rep2{0}); - using ret = quantity>; + using common_rep = decltype(q.count() / v); + using ret = quantity; return ret(ret(q).count() / v); } @@ -286,19 +312,22 @@ namespace units { { Expects(rhs != std::decay_t(0)); - using cq = std::common_type_t, quantity>; + using common_rep = decltype(lhs.count() / rhs.count()); + using cq = common_quantity_t, quantity, common_rep>; return cq(lhs).count() / cq(rhs).count(); } template - requires treat_as_floating_point> || (std::ratio_divide::den == 1) - /* [[nodiscard]] */ constexpr Quantity operator/(const quantity& lhs, - const quantity& rhs) + [[nodiscard]] constexpr Quantity operator/(const quantity& lhs, + const quantity& rhs) + requires treat_as_floating_point || + (std::ratio_divide::den == 1) { Expects(rhs != std::decay_t(0)); + using common_rep = decltype(lhs.count() / rhs.count()); using dim = dimension_divide_t; - using ret = quantity>>, std::common_type_t>; + using ret = quantity>>, common_rep>; return ret(lhs.count() / rhs.count()); } @@ -306,7 +335,8 @@ namespace units { [[nodiscard]] constexpr Quantity operator%(const quantity& q, const Rep2& v) { - using ret = quantity>; + using common_rep = decltype(q.count() % v); + using ret = quantity; return ret(ret(q).count() % v); } @@ -314,7 +344,8 @@ namespace units { [[nodiscard]] constexpr Quantity operator%(const quantity& lhs, const quantity& rhs) { - using ret = std::common_type_t, quantity>; + using common_rep = decltype(lhs.count() % rhs.count()); + using ret = common_quantity_t, quantity, common_rep>; return ret(ret(lhs).count() % ret(rhs).count()); } @@ -323,7 +354,7 @@ namespace units { template [[nodiscard]] constexpr bool operator==(const quantity& lhs, const quantity& rhs) { - using ct = std::common_type_t, quantity>; + using ct = common_quantity_t, quantity>; return ct(lhs).count() == ct(rhs).count(); } @@ -336,7 +367,7 @@ namespace units { template [[nodiscard]] constexpr bool operator<(const quantity& lhs, const quantity& rhs) { - using ct = std::common_type_t, quantity>; + using ct = common_quantity_t, quantity>; return ct(lhs).count() < ct(rhs).count(); } @@ -359,19 +390,3 @@ namespace units { } } // namespace units - -namespace std { - - template - struct common_type, units::quantity> { - using type = units::quantity>; - }; - - // todo: simplified - template - struct common_type, units::quantity> { - using type = units::quantity>>, - std::common_type_t>; - }; - -} // namespace std diff --git a/test/test_quantity.cpp b/test/test_quantity.cpp index 649e0b21..4d11ed76 100644 --- a/test/test_quantity.cpp +++ b/test/test_quantity.cpp @@ -249,11 +249,11 @@ namespace { static_assert(Quantity>); - // common_type + // common_quantity - static_assert(std::is_same_v, length>, length>); - static_assert(std::is_same_v, length>, length>); - static_assert(std::is_same_v, length>, length>); + static_assert(std::is_same_v, length>, length>); + static_assert(std::is_same_v, length>, length>); + static_assert(std::is_same_v, length>, length>); // quantity_cast