Mercurial > lbo > hg > ctmp
changeset 9:25fd2f822fd7
units: simplify usage
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Wed, 25 Mar 2020 16:34:54 +0100 |
parents | b5a45f1fd761 |
children | 43e0e42c373d |
files | src/units.cc |
diffstat | 1 files changed, 42 insertions(+), 49 deletions(-) [+] |
line wrap: on
line diff
--- a/src/units.cc Wed Mar 25 15:44:15 2020 +0100 +++ b/src/units.cc Wed Mar 25 16:34:54 2020 +0100 @@ -32,13 +32,13 @@ }; // Unit definitions -typedef mpl::vector_c<int, 1, 0, 0, 0, 0, 0, 0> uM; -typedef mpl::vector_c<int, 0, 1, 0, 0, 0, 0, 0> uKg; -typedef mpl::vector_c<int, 0, 0, 1, 0, 0, 0, 0> uS; -typedef mpl::vector_c<int, 0, 0, 0, 1, 0, 0, 0> uA; -typedef mpl::vector_c<int, 0, 0, 0, 0, 1, 0, 0> uCd; -typedef mpl::vector_c<int, 0, 0, 0, 0, 0, 1, 0> uSrad; -typedef mpl::vector_c<int, 0, 0, 0, 0, 0, 0, 1> uK; +typedef mpl::vector_c<int, 1, 0, 0, 0, 0, 0, 0> METER; +typedef mpl::vector_c<int, 0, 1, 0, 0, 0, 0, 0> KILOGRAM; +typedef mpl::vector_c<int, 0, 0, 1, 0, 0, 0, 0> SECOND; +typedef mpl::vector_c<int, 0, 0, 0, 1, 0, 0, 0> AMPERE; +typedef mpl::vector_c<int, 0, 0, 0, 0, 1, 0, 0> CANDELA; +typedef mpl::vector_c<int, 0, 0, 0, 0, 0, 1, 0> SRAD; +typedef mpl::vector_c<int, 0, 0, 0, 0, 0, 0, 1> KELVIN; template <typename U> struct unit_name { @@ -52,10 +52,11 @@ EXTRACT_EXPONENT(4); EXTRACT_EXPONENT(5); EXTRACT_EXPONENT(6); -#define FORMAT_UNIT(USYM, UNAME) \ - if (USYM) { \ - s << #UNAME; \ - if (USYM != 1) s << "^" << USYM << " "; \ +#define FORMAT_UNIT(USYM, UNAME) \ + if (USYM) { \ + s << #UNAME; \ + if (USYM != 1) s << "^" << USYM; \ + s << " "; \ } FORMAT_UNIT(U0, m); FORMAT_UNIT(U1, kg); @@ -78,35 +79,16 @@ typedef typename mpl::transform<U1, U2, make_lambda<minus>>::type type; }; -// Unit prototypes contain a unit and know their name. - -template <typename U> -struct unit_proto { - typedef U type; - std::string sym; - unit_proto(void) : sym(unit_name<U>().name()) {} - unit_proto(const std::string& sym) : sym(sym) {} -}; - -static const unit_proto<uM> meter; -static const unit_proto<uKg> kilogram; -static const unit_proto<uS> second; -static const unit_proto<uA> ampere; -static const unit_proto<uCd> candela; -static const unit_proto<uSrad> sterad; -static const unit_proto<uK> kelvin; - // Quantity template <typename N, typename U> struct quantity { N value; - unit_proto<U> unit; // quantity(const quantity<N,U>& other) : value(other.value), // unit(other.unit) {} const quantity<N,U>& operator=(const quantity<N,U>& // other) { value = other.value; unit = other.unit; } - quantity(N val, unit_proto<U> un) : value(val), unit(un) {} + quantity(N val) : value(val) {} operator std::string(void) { std::ostringstream o; o << value << " " << unit_name<U>().name(); @@ -117,25 +99,17 @@ quantity<typename std::common_type<N, N2>::type, U> operator+( const quantity<N2, U>& other) { auto q = quantity<typename std::common_type<N, N2>::type, U>( - value + other.value, unit); + value + other.value); return q; } template <typename N2, typename U2> quantity<typename std::common_type<N, N2>::type, typename multiply_units<U, U2>::type> - operator*(const quantity<N2, U2>& other) { + operator*(const quantity<N2, U2>& other) const { typedef typename multiply_units<U, U2>::type resultunit; auto q = quantity<typename std::common_type<N, N2>::type, resultunit>( - value * other.value, unit_proto<resultunit>()); - return q; - } - - template <typename N2> - quantity<typename std::common_type<N, N2>::type, U> operator*( - const N2& other) { - auto q = quantity<typename std::common_type<N, N2>::type, U>( - value * other, unit_proto<U>()); + value * other.value); return q; } @@ -145,21 +119,40 @@ operator/(const quantity<N2, U2>& other) { typedef typename divide_units<U, U2>::type resultunit; auto q = quantity<typename std::common_type<N, N2>::type, resultunit>( - value / other.value, unit_proto<resultunit>()); + value / other.value); return q; } }; -template <typename N, typename U> -quantity<N, U> make_quant(N val, unit_proto<U> unit_pt) { - quantity<N, U> q(val, unit_pt); +// Scalar multiplication +template <typename N1, typename N2, typename U, + std::enable_if_t<std::is_arithmetic<N1>::value, int> = 0> +quantity<typename std::common_type<N1, N2>::type, U> operator*( + const quantity<N2, U>& second, const N1& first) { + auto q = quantity<typename std::common_type<N1, N2>::type, U>(second.value * + first); return q; } +template <typename N1, typename N2, typename U, + std::enable_if_t<std::is_arithmetic<N1>::value, int> = 0> +quantity<typename std::common_type<N1, N2>::type, U> operator*( + const N1& first, const quantity<N2, U>& second) { + return second * first; +} + +static const quantity<int, METER> meter(1); +static const quantity<int, SECOND> second(1); +static const quantity<int, KILOGRAM> kilogram(1); +static const quantity<int, AMPERE> ampere(1); +static const quantity<int, CANDELA> candela(1); +static const quantity<int, SRAD> srad(1); +static const quantity<int, KELVIN> kelvin(1); int main(void) { - auto x = make_quant(33.0f, second); - auto y = make_quant(30.0f, meter); - auto z = (x * x) / (x * y * 4.5); + auto force = 1 * kilogram * meter / (second * second); + auto x = 13.2 * force; + auto y = 2.3; + auto z = (x * x) / (x * y); std::cout << std::string(z) << std::endl; return 0; }