diff --git a/example/glide_computer/include/geographic.h b/example/glide_computer/include/geographic.h index eba165c3..e94f2894 100644 --- a/example/glide_computer/include/geographic.h +++ b/example/glide_computer/include/geographic.h @@ -62,29 +62,29 @@ std::basic_ostream& operator<<(std::basic_ostream& inline namespace literals { -constexpr auto operator"" _N(long double v) { return latitude(latitude::rep(v)); } -constexpr auto operator"" _S(long double v) { return latitude(latitude::rep(v)); } -constexpr auto operator"" _E(long double v) { return longitude(longitude::rep(v)); } -constexpr auto operator"" _W(long double v) { return longitude(longitude::rep(v)); } -constexpr auto operator"" _N(unsigned long long v) +constexpr latitude operator"" _N(long double v) { return v * mp_units::si::degree; } +constexpr latitude operator"" _S(long double v) { return -v * mp_units::si::degree; } +constexpr longitude operator"" _E(long double v) { return v * mp_units::si::degree; } +constexpr longitude operator"" _W(long double v) { return -v * mp_units::si::degree; } +constexpr latitude operator"" _N(unsigned long long v) { gsl_ExpectsAudit(std::in_range(v)); - return latitude(latitude::rep(static_cast(v))); + return static_cast(v) * mp_units::si::degree; } -constexpr auto operator"" _S(unsigned long long v) +constexpr latitude operator"" _S(unsigned long long v) { gsl_ExpectsAudit(std::in_range(v)); - return latitude(-latitude::rep(static_cast(v))); + return -static_cast(v) * mp_units::si::degree; } -constexpr auto operator"" _E(unsigned long long v) +constexpr longitude operator"" _E(unsigned long long v) { gsl_ExpectsAudit(std::in_range(v)); - return longitude(longitude::rep(static_cast(v))); + return static_cast(v) * mp_units::si::degree; } -constexpr auto operator"" _W(unsigned long long v) +constexpr longitude operator"" _W(unsigned long long v) { gsl_ExpectsAudit(std::in_range(v)); - return longitude(-longitude::rep(static_cast(v))); + return -static_cast(v) * mp_units::si::degree; } } // namespace literals diff --git a/example/linear_algebra.cpp b/example/linear_algebra.cpp index ab33e043..9ec0a94b 100644 --- a/example/linear_algebra.cpp +++ b/example/linear_algebra.cpp @@ -89,8 +89,8 @@ void quantity_of_vector_cast() { std::cout << "\nquantity_of_vector_cast:\n"; - quantity> v{vector{1001, 1002, 1003}}; - quantity> u{vector{3, 2, 1}}; + auto v = vector{1001, 1002, 1003} * isq::position_vector[m]; + auto u = vector{3, 2, 1} * isq::position_vector[km]; std::cout << "v = " << v << "\n"; std::cout << "u = " << u << "\n"; @@ -103,7 +103,7 @@ void quantity_of_vector_multiply_by_scalar_value() { std::cout << "\nquantity_of_vector_multiply_scalar_value:\n"; - quantity> v{vector{1, 2, 3}}; + auto v = vector{1, 2, 3} * isq::position_vector[m]; std::cout << "v = " << v << "\n"; @@ -114,7 +114,7 @@ void quantity_of_vector_divide_by_scalar_value() { std::cout << "\nquantity_of_vector_divide_scalar_value:\n"; - quantity> v{vector{2, 4, 6}}; + auto v = vector{2, 4, 6} * isq::position_vector[m]; std::cout << "v = " << v << "\n"; @@ -131,9 +131,9 @@ void quantity_of_vector_add() // auto t = vector{3, 2, 1} * isq::position_vector[km]; // quantity> v{vector{1, 2, 3}}; // should not compile - quantity> v{vector{1, 2, 3}}; - quantity> u{vector{3, 2, 1}}; - quantity> t{vector{3, 2, 1}}; + auto v = vector{1, 2, 3} * isq::position_vector[m]; + auto u = vector{3, 2, 1} * isq::position_vector[m]; + auto t = vector{3, 2, 1} * isq::position_vector[km]; std::cout << "v = " << v << "\n"; std::cout << "u = " << u << "\n"; @@ -147,9 +147,9 @@ void quantity_of_vector_subtract() { std::cout << "\nquantity_of_vector_subtract:\n"; - quantity> v{vector{1, 2, 3}}; - quantity> u{vector{3, 2, 1}}; - quantity> t{vector{3, 2, 1}}; + auto v = vector{1, 2, 3} * isq::position_vector[m]; + auto u = vector{3, 2, 1} * isq::position_vector[m]; + auto t = vector{3, 2, 1} * isq::position_vector[km]; std::cout << "v = " << v << "\n"; std::cout << "u = " << u << "\n"; @@ -163,7 +163,7 @@ void quantity_of_vector_divide_by_scalar_quantity() { std::cout << "\nquantity_of_vector_divide_scalar:\n"; - quantity> pos{vector{30, 20, 10}}; + auto pos = vector{30, 20, 10} * isq::position_vector[km]; auto dur = 2 * isq::duration[h]; quantity> v = pos / dur; diff --git a/src/core/include/mp_units/bits/sudo_cast.h b/src/core/include/mp_units/bits/sudo_cast.h index d16041b4..5e01a99b 100644 --- a/src/core/include/mp_units/bits/sudo_cast.h +++ b/src/core/include/mp_units/bits/sudo_cast.h @@ -51,10 +51,10 @@ template { if constexpr (get_unit(R) == To::unit) { // no scaling of the number needed - return To(static_cast(q.number())); // this is the only (and recommended) way to do - // a truncating conversion on a number, so we are - // using static_cast to suppress all the compiler - // warnings on conversions + return static_cast(q.number()) * To::reference; // this is the only (and recommended) way to do + // a truncating conversion on a number, so we are + // using static_cast to suppress all the compiler + // warnings on conversions } else { // scale the number using rep_type = decltype([] { @@ -85,7 +85,8 @@ template constexpr Magnitude auto irr = c_mag * (den / num); constexpr auto val = [](Magnitude auto m) { return get_value(m); }; - return To(static_cast(static_cast(q.number()) * val(num) / val(den) * val(irr))); + return static_cast(static_cast(q.number()) * val(num) / val(den) * val(irr)) * + To::reference; } } diff --git a/src/core/include/mp_units/quantity.h b/src/core/include/mp_units/quantity.h index 5e0dfe8d..445bb464 100644 --- a/src/core/include/mp_units/quantity.h +++ b/src/core/include/mp_units/quantity.h @@ -121,12 +121,6 @@ public: quantity(const quantity&) = default; quantity(quantity&&) = default; - template - requires detail::RepSafeConstructibleFrom - constexpr explicit(!detail::QuantityOne) quantity(Value&& v) : number_(std::forward(v)) - { - } - template Q> constexpr explicit(false) quantity(const Q& q) : number_(detail::sudo_cast(q).number()) { @@ -439,6 +433,17 @@ public: #endif [[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity& rhs) = default; + +private: + template + requires RepresentationOf, get_quantity_spec(R2{}).character> + friend constexpr quantity> operator*(Rep2&& lhs, R2); + + template + requires detail::RepSafeConstructibleFrom + constexpr explicit quantity(Value&& v) : number_(std::forward(v)) + { + } }; // CTAD @@ -465,7 +470,7 @@ template { constexpr auto ref = common_reference(Q1::reference, Q2::reference); using ret = quantity; - return ret(ret(lhs).number() + ret(rhs).number()); + return (ret(lhs).number() + ret(rhs).number()) * ref; } template @@ -476,7 +481,7 @@ template { constexpr auto ref = common_reference(Q1::reference, Q2::reference); using ret = quantity; - return ret(ret(lhs).number() - ret(rhs).number()); + return (ret(lhs).number() - ret(rhs).number()) * ref; } template diff --git a/src/utility/include/mp_units/math.h b/src/utility/include/mp_units/math.h index aeacf88a..4f671fd9 100644 --- a/src/utility/include/mp_units/math.h +++ b/src/utility/include/mp_units/math.h @@ -61,8 +61,8 @@ template return q; } else { using std::pow; - return quantity(Q::quantity_spec), pow(Q::unit)>{}, rep>( - static_cast(pow(q.number(), static_cast(Num) / static_cast(Den)))); + return static_cast(pow(q.number(), static_cast(Num) / static_cast(Den))) * + reference(Q::quantity_spec), pow(Q::unit)>{}; } } @@ -80,8 +80,7 @@ template { using rep = TYPENAME Q::rep; using std::sqrt; - return quantity(Q::quantity_spec), pow<1, 2>(Q::unit)>{}, rep>( - static_cast(sqrt(q.number()))); + return static_cast(sqrt(q.number())) * reference(Q::quantity_spec), pow<1, 2>(Q::unit)>{}; } /** @@ -98,8 +97,7 @@ template { using rep = TYPENAME Q::rep; using std::cbrt; - return quantity(Q::quantity_spec), pow<1, 3>(Q::unit)>{}, rep>( - static_cast(cbrt(q.number()))); + return static_cast(cbrt(q.number())) * reference(Q::quantity_spec), pow<1, 3>(Q::unit)>{}; } /** @@ -171,10 +169,9 @@ template if constexpr (treat_as_floating_point) { using std::floor; if constexpr (To == get_unit(R)) { - return quantity{}, Rep>(floor(q.number())); + return floor(q.number()) * reference{}; } else { - return handle_signed_results( - quantity{}, Rep>(floor(value_cast(q).number()))); + return handle_signed_results(floor(value_cast(q).number()) * reference{}); } } else { if constexpr (To == get_unit(R)) { @@ -208,10 +205,9 @@ template if constexpr (treat_as_floating_point) { using std::ceil; if constexpr (To == get_unit(R)) { - return quantity{}, Rep>(ceil(q.number())); + return ceil(q.number()) * reference{}; } else { - return handle_signed_results( - quantity{}, Rep>(ceil(value_cast(q).number()))); + return handle_signed_results(ceil(value_cast(q).number()) * reference{}); } } else { if constexpr (To == get_unit(R)) { @@ -242,7 +238,7 @@ template if constexpr (To == get_unit(R)) { if constexpr (treat_as_floating_point) { using std::round; - return quantity{}, Rep>(round(q.number())); + return round(q.number()) * reference{}; } else { return value_cast(q); } @@ -306,7 +302,7 @@ template Q> requires requires { sin(q.number()); } || requires { std::sin(q.number()); } { using std::sin; - return quantity{sin(q[si::radian].number())}; + return sin(q[si::radian].number()) * one; } template Q> @@ -315,7 +311,7 @@ template Q> requires requires { cos(q.number()); } || requires { std::cos(q.number()); } { using std::cos; - return quantity{cos(q[si::radian].number())}; + return cos(q[si::radian].number()) * one; } template Q> @@ -324,7 +320,7 @@ template Q> requires requires { tan(q.number()); } || requires { std::tan(q.number()); } { using std::tan; - return quantity{tan(q[si::radian].number())}; + return tan(q[si::radian].number()) * one; } template Q>