From e8669856683961c88d597db09dfc5d6fb25ec511 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Wed, 14 Nov 2018 22:36:02 +0100 Subject: [PATCH] Strong units support added --- src/include/units/quantity.h | 14 +++++++------- src/include/units/si/frequency.h | 25 ++++++++++++++++++------- src/include/units/si/length.h | 15 +++++++++++---- src/include/units/si/time.h | 23 +++++++++++++++++------ src/include/units/si/velocity.h | 11 ++++++++--- src/include/units/unit.h | 18 +++++++++--------- test/test_quantity.cpp | 14 ++++++++------ 7 files changed, 78 insertions(+), 42 deletions(-) diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index 526af801..9e04c121 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -245,22 +245,22 @@ namespace units { template requires treat_as_floating_point> || std::ratio_multiply::den == 1 - quantity, unit, std::ratio_multiply>, std::common_type_t> + quantity, unit_traits_t, std::ratio_multiply>>, std::common_type_t> constexpr operator*(const quantity& lhs, const quantity& rhs) { using dim = dimension_multiply_t; - using ret = quantity>, std::common_type_t>; + using ret = quantity>>, std::common_type_t>; return ret(lhs.count() * rhs.count()); } template - quantity, unit, std::ratio>, std::common_type_t> + quantity, unit_traits_t, std::ratio>>, std::common_type_t> constexpr operator/(const Rep1& v, const quantity& q) { using dim = dim_invert_t; - using ret = quantity>, std::common_type_t>; + using ret = quantity>>, std::common_type_t>; using den = quantity>; return ret(v / den(q).count()); } @@ -285,12 +285,12 @@ namespace units { template requires treat_as_floating_point> || std::ratio_divide::den == 1 - quantity, unit, std::ratio_divide>, std::common_type_t> + quantity, unit_traits_t, std::ratio_divide>>, std::common_type_t> constexpr operator/(const quantity& lhs, const quantity& rhs) { using dim = dimension_divide_t; - using ret = quantity>, std::common_type_t>; + using ret = quantity>>, std::common_type_t>; return ret(lhs.count() / rhs.count()); } @@ -364,7 +364,7 @@ namespace std { // todo: simplified template struct common_type, units::quantity> { - using type = units::quantity>, + using type = units::quantity>>, std::common_type_t>; }; diff --git a/src/include/units/si/frequency.h b/src/include/units/si/frequency.h index 38276e0a..924d3764 100644 --- a/src/include/units/si/frequency.h +++ b/src/include/units/si/frequency.h @@ -27,16 +27,27 @@ namespace units { - - using millihertz = unit; - using hertz = unit>; - using kilohertz = unit; - using megahertz = unit; - using gigahertz = unit; - using terahertz = unit; struct dimension_frequency : make_dimension_t> {}; template<> struct dimension_traits : std::type_identity {}; + struct millihertz : unit {}; + template<> struct unit_traits : std::type_identity {}; + + struct hertz : unit> {}; + template<> struct unit_traits : std::type_identity {}; + + struct kilohertz : unit {}; + template<> struct unit_traits : std::type_identity {}; + + struct megahertz : unit {}; + template<> struct unit_traits : std::type_identity {}; + + struct gigahertz : unit {}; + template<> struct unit_traits : std::type_identity {}; + + struct terahertz : unit {}; + template<> struct unit_traits : std::type_identity {}; + template using frequency = quantity; diff --git a/src/include/units/si/length.h b/src/include/units/si/length.h index e7bd8de2..08b274e5 100644 --- a/src/include/units/si/length.h +++ b/src/include/units/si/length.h @@ -30,10 +30,17 @@ namespace units { struct dimension_length : make_dimension_t> {}; template<> struct dimension_traits : std::type_identity {}; - using millimeter = unit; - using centimeter = unit>; - using meter = unit>; - using kilometer = unit; + struct millimeter : unit {}; + template<> struct unit_traits : std::type_identity {}; + + struct centimeter : unit> {}; + template<> struct unit_traits : std::type_identity {}; + + struct meter : unit> {}; + template<> struct unit_traits : std::type_identity {}; + + struct kilometer : unit {}; + template<> struct unit_traits : std::type_identity {}; template using length = quantity; diff --git a/src/include/units/si/time.h b/src/include/units/si/time.h index e48ed372..10f903fa 100644 --- a/src/include/units/si/time.h +++ b/src/include/units/si/time.h @@ -27,15 +27,26 @@ namespace units { - using nanosecond = unit; - using microsecond = unit; - using millisecond = unit; - using second = unit>; - using minute = unit>; - using hour = unit>; struct dimension_time : make_dimension_t> {}; template<> struct dimension_traits : std::type_identity {}; + struct nanosecond : unit {}; + template<> struct unit_traits : std::type_identity {}; + + struct microsecond : unit {}; + template<> struct unit_traits : std::type_identity {}; + + struct millisecond : unit {}; + template<> struct unit_traits : std::type_identity {}; + + struct second : unit> {}; + template<> struct unit_traits : std::type_identity {}; + + struct minute : unit> {}; + template<> struct unit_traits : std::type_identity {}; + + struct hour : unit> {}; + template<> struct unit_traits : std::type_identity {}; template using time = quantity; diff --git a/src/include/units/si/velocity.h b/src/include/units/si/velocity.h index d8c85172..5b191fac 100644 --- a/src/include/units/si/velocity.h +++ b/src/include/units/si/velocity.h @@ -31,9 +31,14 @@ namespace units { struct dimension_velocity : make_dimension_t, exp> {}; template<> struct dimension_traits : std::type_identity {}; - using meter_per_second = unit>; - using kilometer_per_hour = unit>; - using mile_per_hour = unit>; + struct meter_per_second : unit> {}; + template<> struct unit_traits : std::type_identity {}; + + struct kilometer_per_hour : unit> {}; + template<> struct unit_traits : std::type_identity {}; + + struct mile_per_hour : unit> {}; + template<> struct unit_traits : std::type_identity {}; template using velocity = quantity; diff --git a/src/include/units/unit.h b/src/include/units/unit.h index ea139a72..b4eddba2 100644 --- a/src/include/units/unit.h +++ b/src/include/units/unit.h @@ -28,7 +28,7 @@ namespace units { template - struct unit { + struct unit : std::type_identity> { using dimension = D; using ratio = R; static_assert(ratio::num > 0, "ratio must be positive"); @@ -47,14 +47,14 @@ namespace units { } template - concept bool Unit = detail::is_unit; + concept bool Unit = detail::is_unit; -// template -// auto operator/(U1, U2) -// { -// return ; -// } -// -// unit, std::ratio_divide> + // dimension_traits + + template + struct unit_traits : std::type_identity {}; + + template + using unit_traits_t = typename unit_traits::type; } // namespace units diff --git a/test/test_quantity.cpp b/test/test_quantity.cpp index 664c6af7..00aebc3a 100644 --- a/test/test_quantity.cpp +++ b/test/test_quantity.cpp @@ -21,6 +21,7 @@ // SOFTWARE. #include "units/si/velocity.h" +#include "units/si/frequency.h" #include #include @@ -190,12 +191,13 @@ namespace { static_assert(std::is_same_v() + length()), quantity>); static_assert(std::is_same_v() + length()), quantity>); - static_assert(std::is_same_v() + length()), quantity>, double>>); + static_assert(std::is_same_v() + length()), quantity>); static_assert(std::is_same_v() - length()), quantity>); - static_assert(std::is_same_v() - length()), quantity>, double>>); + static_assert(std::is_same_v() - length()), quantity>); static_assert(std::is_same_v() * 1.0), quantity>); static_assert(std::is_same_v()), quantity>); - static_assert(std::is_same_v() * units::time()), quantity>, int>>); + static_assert(std::is_same_v() * units::time()), quantity>); + static_assert(std::is_same_v()), quantity>); static_assert(std::is_same_v() / 1.0), quantity>); static_assert(std::is_same_v() / length()), double>); static_assert(std::is_same_v() / length()), double>); @@ -253,9 +255,9 @@ namespace { // common_type - static_assert(std::is_same_v, length>, length>, int>>); - static_assert(std::is_same_v, length>, length>, long long>>); - static_assert(std::is_same_v, length>, length>, double>>); + 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