forked from mpusz/mp-units
refactor: Quantity no longer can be constructed with a raw value
Resolves #434
This commit is contained in:
@@ -62,29 +62,29 @@ std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>&
|
|||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
constexpr auto operator"" _N(long double v) { return latitude<long double>(latitude<long double>::rep(v)); }
|
constexpr latitude<long double> operator"" _N(long double v) { return v * mp_units::si::degree; }
|
||||||
constexpr auto operator"" _S(long double v) { return latitude<long double>(latitude<long double>::rep(v)); }
|
constexpr latitude<long double> operator"" _S(long double v) { return -v * mp_units::si::degree; }
|
||||||
constexpr auto operator"" _E(long double v) { return longitude<long double>(longitude<long double>::rep(v)); }
|
constexpr longitude<long double> operator"" _E(long double v) { return v * mp_units::si::degree; }
|
||||||
constexpr auto operator"" _W(long double v) { return longitude<long double>(longitude<long double>::rep(v)); }
|
constexpr longitude<long double> operator"" _W(long double v) { return -v * mp_units::si::degree; }
|
||||||
constexpr auto operator"" _N(unsigned long long v)
|
constexpr latitude<std::int64_t> operator"" _N(unsigned long long v)
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
|
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
|
||||||
return latitude<std::int64_t>(latitude<std::int64_t>::rep(static_cast<std::int64_t>(v)));
|
return static_cast<std::int64_t>(v) * mp_units::si::degree;
|
||||||
}
|
}
|
||||||
constexpr auto operator"" _S(unsigned long long v)
|
constexpr latitude<std::int64_t> operator"" _S(unsigned long long v)
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
|
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
|
||||||
return latitude<std::int64_t>(-latitude<std::int64_t>::rep(static_cast<std::int64_t>(v)));
|
return -static_cast<std::int64_t>(v) * mp_units::si::degree;
|
||||||
}
|
}
|
||||||
constexpr auto operator"" _E(unsigned long long v)
|
constexpr longitude<std::int64_t> operator"" _E(unsigned long long v)
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
|
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
|
||||||
return longitude<std::int64_t>(longitude<std::int64_t>::rep(static_cast<std::int64_t>(v)));
|
return static_cast<std::int64_t>(v) * mp_units::si::degree;
|
||||||
}
|
}
|
||||||
constexpr auto operator"" _W(unsigned long long v)
|
constexpr longitude<std::int64_t> operator"" _W(unsigned long long v)
|
||||||
{
|
{
|
||||||
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
|
gsl_ExpectsAudit(std::in_range<std::int64_t>(v));
|
||||||
return longitude<std::int64_t>(-longitude<std::int64_t>::rep(static_cast<std::int64_t>(v)));
|
return -static_cast<std::int64_t>(v) * mp_units::si::degree;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
@@ -89,8 +89,8 @@ void quantity_of_vector_cast()
|
|||||||
{
|
{
|
||||||
std::cout << "\nquantity_of_vector_cast:\n";
|
std::cout << "\nquantity_of_vector_cast:\n";
|
||||||
|
|
||||||
quantity<isq::position_vector[m], vector<int>> v{vector<int>{1001, 1002, 1003}};
|
auto v = vector<int>{1001, 1002, 1003} * isq::position_vector[m];
|
||||||
quantity<isq::position_vector[km], vector<int>> u{vector<int>{3, 2, 1}};
|
auto u = vector<int>{3, 2, 1} * isq::position_vector[km];
|
||||||
|
|
||||||
std::cout << "v = " << v << "\n";
|
std::cout << "v = " << v << "\n";
|
||||||
std::cout << "u = " << u << "\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";
|
std::cout << "\nquantity_of_vector_multiply_scalar_value:\n";
|
||||||
|
|
||||||
quantity<isq::position_vector[m], vector<int>> v{vector<int>{1, 2, 3}};
|
auto v = vector<int>{1, 2, 3} * isq::position_vector[m];
|
||||||
|
|
||||||
std::cout << "v = " << v << "\n";
|
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";
|
std::cout << "\nquantity_of_vector_divide_scalar_value:\n";
|
||||||
|
|
||||||
quantity<isq::position_vector[m], vector<int>> v{vector<int>{2, 4, 6}};
|
auto v = vector<int>{2, 4, 6} * isq::position_vector[m];
|
||||||
|
|
||||||
std::cout << "v = " << v << "\n";
|
std::cout << "v = " << v << "\n";
|
||||||
|
|
||||||
@@ -131,9 +131,9 @@ void quantity_of_vector_add()
|
|||||||
// auto t = vector<int>{3, 2, 1} * isq::position_vector[km];
|
// auto t = vector<int>{3, 2, 1} * isq::position_vector[km];
|
||||||
|
|
||||||
// quantity<isq::distance[m], vector<int>> v{vector<int>{1, 2, 3}}; // should not compile
|
// quantity<isq::distance[m], vector<int>> v{vector<int>{1, 2, 3}}; // should not compile
|
||||||
quantity<isq::position_vector[m], vector<int>> v{vector<int>{1, 2, 3}};
|
auto v = vector<int>{1, 2, 3} * isq::position_vector[m];
|
||||||
quantity<isq::position_vector[m], vector<int>> u{vector<int>{3, 2, 1}};
|
auto u = vector<int>{3, 2, 1} * isq::position_vector[m];
|
||||||
quantity<isq::position_vector[km], vector<int>> t{vector<int>{3, 2, 1}};
|
auto t = vector<int>{3, 2, 1} * isq::position_vector[km];
|
||||||
|
|
||||||
std::cout << "v = " << v << "\n";
|
std::cout << "v = " << v << "\n";
|
||||||
std::cout << "u = " << u << "\n";
|
std::cout << "u = " << u << "\n";
|
||||||
@@ -147,9 +147,9 @@ void quantity_of_vector_subtract()
|
|||||||
{
|
{
|
||||||
std::cout << "\nquantity_of_vector_subtract:\n";
|
std::cout << "\nquantity_of_vector_subtract:\n";
|
||||||
|
|
||||||
quantity<isq::position_vector[m], vector<int>> v{vector<int>{1, 2, 3}};
|
auto v = vector<int>{1, 2, 3} * isq::position_vector[m];
|
||||||
quantity<isq::position_vector[m], vector<int>> u{vector<int>{3, 2, 1}};
|
auto u = vector<int>{3, 2, 1} * isq::position_vector[m];
|
||||||
quantity<isq::position_vector[km], vector<int>> t{vector<int>{3, 2, 1}};
|
auto t = vector<int>{3, 2, 1} * isq::position_vector[km];
|
||||||
|
|
||||||
std::cout << "v = " << v << "\n";
|
std::cout << "v = " << v << "\n";
|
||||||
std::cout << "u = " << u << "\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";
|
std::cout << "\nquantity_of_vector_divide_scalar:\n";
|
||||||
|
|
||||||
quantity<isq::position_vector[km], vector<int>> pos{vector<int>{30, 20, 10}};
|
auto pos = vector<int>{30, 20, 10} * isq::position_vector[km];
|
||||||
auto dur = 2 * isq::duration[h];
|
auto dur = 2 * isq::duration[h];
|
||||||
quantity<isq::velocity[km / h], vector<int>> v = pos / dur;
|
quantity<isq::velocity[km / h], vector<int>> v = pos / dur;
|
||||||
|
|
||||||
|
@@ -51,10 +51,10 @@ template<Quantity To, auto R, typename Rep>
|
|||||||
{
|
{
|
||||||
if constexpr (get_unit(R) == To::unit) {
|
if constexpr (get_unit(R) == To::unit) {
|
||||||
// no scaling of the number needed
|
// no scaling of the number needed
|
||||||
return To(static_cast<TYPENAME To::rep>(q.number())); // this is the only (and recommended) way to do
|
return static_cast<TYPENAME To::rep>(q.number()) * To::reference; // this is the only (and recommended) way to do
|
||||||
// a truncating conversion on a number, so we are
|
// a truncating conversion on a number, so we are
|
||||||
// using static_cast to suppress all the compiler
|
// using static_cast to suppress all the compiler
|
||||||
// warnings on conversions
|
// warnings on conversions
|
||||||
} else {
|
} else {
|
||||||
// scale the number
|
// scale the number
|
||||||
using rep_type = decltype([] {
|
using rep_type = decltype([] {
|
||||||
@@ -85,7 +85,8 @@ template<Quantity To, auto R, typename Rep>
|
|||||||
constexpr Magnitude auto irr = c_mag * (den / num);
|
constexpr Magnitude auto irr = c_mag * (den / num);
|
||||||
|
|
||||||
constexpr auto val = [](Magnitude auto m) { return get_value<multiplier_type>(m); };
|
constexpr auto val = [](Magnitude auto m) { return get_value<multiplier_type>(m); };
|
||||||
return To(static_cast<TYPENAME To::rep>(static_cast<rep_type>(q.number()) * val(num) / val(den) * val(irr)));
|
return static_cast<TYPENAME To::rep>(static_cast<rep_type>(q.number()) * val(num) / val(den) * val(irr)) *
|
||||||
|
To::reference;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -121,12 +121,6 @@ public:
|
|||||||
quantity(const quantity&) = default;
|
quantity(const quantity&) = default;
|
||||||
quantity(quantity&&) = default;
|
quantity(quantity&&) = default;
|
||||||
|
|
||||||
template<typename Value>
|
|
||||||
requires detail::RepSafeConstructibleFrom<rep, Value>
|
|
||||||
constexpr explicit(!detail::QuantityOne<quantity>) quantity(Value&& v) : number_(std::forward<Value>(v))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<detail::QuantityConvertibleTo<quantity> Q>
|
template<detail::QuantityConvertibleTo<quantity> Q>
|
||||||
constexpr explicit(false) quantity(const Q& q) : number_(detail::sudo_cast<quantity>(q).number())
|
constexpr explicit(false) quantity(const Q& q) : number_(detail::sudo_cast<quantity>(q).number())
|
||||||
{
|
{
|
||||||
@@ -439,6 +433,17 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity& rhs) = default;
|
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity& rhs) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<Reference R2, typename Rep2>
|
||||||
|
requires RepresentationOf<std::remove_cvref_t<Rep2>, get_quantity_spec(R2{}).character>
|
||||||
|
friend constexpr quantity<R2{}, std::remove_cvref_t<Rep2>> operator*(Rep2&& lhs, R2);
|
||||||
|
|
||||||
|
template<typename Value>
|
||||||
|
requires detail::RepSafeConstructibleFrom<rep, Value>
|
||||||
|
constexpr explicit quantity(Value&& v) : number_(std::forward<Value>(v))
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// CTAD
|
// CTAD
|
||||||
@@ -465,7 +470,7 @@ template<Quantity Q1, Quantity Q2>
|
|||||||
{
|
{
|
||||||
constexpr auto ref = common_reference(Q1::reference, Q2::reference);
|
constexpr auto ref = common_reference(Q1::reference, Q2::reference);
|
||||||
using ret = quantity<ref, decltype(lhs.number() + rhs.number())>;
|
using ret = quantity<ref, decltype(lhs.number() + rhs.number())>;
|
||||||
return ret(ret(lhs).number() + ret(rhs).number());
|
return (ret(lhs).number() + ret(rhs).number()) * ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Quantity Q1, Quantity Q2>
|
template<Quantity Q1, Quantity Q2>
|
||||||
@@ -476,7 +481,7 @@ template<Quantity Q1, Quantity Q2>
|
|||||||
{
|
{
|
||||||
constexpr auto ref = common_reference(Q1::reference, Q2::reference);
|
constexpr auto ref = common_reference(Q1::reference, Q2::reference);
|
||||||
using ret = quantity<ref, decltype(lhs.number() - rhs.number())>;
|
using ret = quantity<ref, decltype(lhs.number() - rhs.number())>;
|
||||||
return ret(ret(lhs).number() - ret(rhs).number());
|
return (ret(lhs).number() - ret(rhs).number()) * ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Quantity Q1, Quantity Q2>
|
template<Quantity Q1, Quantity Q2>
|
||||||
|
@@ -61,8 +61,8 @@ template<std::intmax_t Num, std::intmax_t Den = 1, Quantity Q>
|
|||||||
return q;
|
return q;
|
||||||
} else {
|
} else {
|
||||||
using std::pow;
|
using std::pow;
|
||||||
return quantity<reference<pow<Num, Den>(Q::quantity_spec), pow<Num, Den>(Q::unit)>{}, rep>(
|
return static_cast<rep>(pow(q.number(), static_cast<double>(Num) / static_cast<double>(Den))) *
|
||||||
static_cast<rep>(pow(q.number(), static_cast<double>(Num) / static_cast<double>(Den))));
|
reference<pow<Num, Den>(Q::quantity_spec), pow<Num, Den>(Q::unit)>{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +80,7 @@ template<Quantity Q>
|
|||||||
{
|
{
|
||||||
using rep = TYPENAME Q::rep;
|
using rep = TYPENAME Q::rep;
|
||||||
using std::sqrt;
|
using std::sqrt;
|
||||||
return quantity<reference<pow<1, 2>(Q::quantity_spec), pow<1, 2>(Q::unit)>{}, rep>(
|
return static_cast<rep>(sqrt(q.number())) * reference<pow<1, 2>(Q::quantity_spec), pow<1, 2>(Q::unit)>{};
|
||||||
static_cast<rep>(sqrt(q.number())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,8 +97,7 @@ template<Quantity Q>
|
|||||||
{
|
{
|
||||||
using rep = TYPENAME Q::rep;
|
using rep = TYPENAME Q::rep;
|
||||||
using std::cbrt;
|
using std::cbrt;
|
||||||
return quantity<reference<pow<1, 3>(Q::quantity_spec), pow<1, 3>(Q::unit)>{}, rep>(
|
return static_cast<rep>(cbrt(q.number())) * reference<pow<1, 3>(Q::quantity_spec), pow<1, 3>(Q::unit)>{};
|
||||||
static_cast<rep>(cbrt(q.number())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,10 +169,9 @@ template<Unit auto To, auto R, typename Rep>
|
|||||||
if constexpr (treat_as_floating_point<Rep>) {
|
if constexpr (treat_as_floating_point<Rep>) {
|
||||||
using std::floor;
|
using std::floor;
|
||||||
if constexpr (To == get_unit(R)) {
|
if constexpr (To == get_unit(R)) {
|
||||||
return quantity<reference<get_quantity_spec(R), To>{}, Rep>(floor(q.number()));
|
return floor(q.number()) * reference<get_quantity_spec(R), To>{};
|
||||||
} else {
|
} else {
|
||||||
return handle_signed_results(
|
return handle_signed_results(floor(value_cast<To>(q).number()) * reference<get_quantity_spec(R), To>{});
|
||||||
quantity<reference<get_quantity_spec(R), To>{}, Rep>(floor(value_cast<To>(q).number())));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if constexpr (To == get_unit(R)) {
|
if constexpr (To == get_unit(R)) {
|
||||||
@@ -208,10 +205,9 @@ template<Unit auto To, auto R, typename Rep>
|
|||||||
if constexpr (treat_as_floating_point<Rep>) {
|
if constexpr (treat_as_floating_point<Rep>) {
|
||||||
using std::ceil;
|
using std::ceil;
|
||||||
if constexpr (To == get_unit(R)) {
|
if constexpr (To == get_unit(R)) {
|
||||||
return quantity<reference<get_quantity_spec(R), To>{}, Rep>(ceil(q.number()));
|
return ceil(q.number()) * reference<get_quantity_spec(R), To>{};
|
||||||
} else {
|
} else {
|
||||||
return handle_signed_results(
|
return handle_signed_results(ceil(value_cast<To>(q).number()) * reference<get_quantity_spec(R), To>{});
|
||||||
quantity<reference<get_quantity_spec(R), To>{}, Rep>(ceil(value_cast<To>(q).number())));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if constexpr (To == get_unit(R)) {
|
if constexpr (To == get_unit(R)) {
|
||||||
@@ -242,7 +238,7 @@ template<Unit auto To, auto R, typename Rep>
|
|||||||
if constexpr (To == get_unit(R)) {
|
if constexpr (To == get_unit(R)) {
|
||||||
if constexpr (treat_as_floating_point<Rep>) {
|
if constexpr (treat_as_floating_point<Rep>) {
|
||||||
using std::round;
|
using std::round;
|
||||||
return quantity<reference<get_quantity_spec(R), To>{}, Rep>(round(q.number()));
|
return round(q.number()) * reference<get_quantity_spec(R), To>{};
|
||||||
} else {
|
} else {
|
||||||
return value_cast<To>(q);
|
return value_cast<To>(q);
|
||||||
}
|
}
|
||||||
@@ -306,7 +302,7 @@ template<QuantityOf<angular_measure> Q>
|
|||||||
requires requires { sin(q.number()); } || requires { std::sin(q.number()); }
|
requires requires { sin(q.number()); } || requires { std::sin(q.number()); }
|
||||||
{
|
{
|
||||||
using std::sin;
|
using std::sin;
|
||||||
return quantity{sin(q[si::radian].number())};
|
return sin(q[si::radian].number()) * one;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityOf<angular_measure> Q>
|
template<QuantityOf<angular_measure> Q>
|
||||||
@@ -315,7 +311,7 @@ template<QuantityOf<angular_measure> Q>
|
|||||||
requires requires { cos(q.number()); } || requires { std::cos(q.number()); }
|
requires requires { cos(q.number()); } || requires { std::cos(q.number()); }
|
||||||
{
|
{
|
||||||
using std::cos;
|
using std::cos;
|
||||||
return quantity{cos(q[si::radian].number())};
|
return cos(q[si::radian].number()) * one;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityOf<angular_measure> Q>
|
template<QuantityOf<angular_measure> Q>
|
||||||
@@ -324,7 +320,7 @@ template<QuantityOf<angular_measure> Q>
|
|||||||
requires requires { tan(q.number()); } || requires { std::tan(q.number()); }
|
requires requires { tan(q.number()); } || requires { std::tan(q.number()); }
|
||||||
{
|
{
|
||||||
using std::tan;
|
using std::tan;
|
||||||
return quantity{tan(q[si::radian].number())};
|
return tan(q[si::radian].number()) * one;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityOf<dimension_one> Q>
|
template<QuantityOf<dimension_one> Q>
|
||||||
|
Reference in New Issue
Block a user