Strong dimensions support added

This commit is contained in:
Mateusz Pusz
2018-11-14 22:14:44 +01:00
parent 297b71efcf
commit 7205dc2cb9
7 changed files with 50 additions and 17 deletions

View File

@ -26,6 +26,16 @@
#include <ratio> #include <ratio>
#include <type_traits> #include <type_traits>
namespace std {
template<typename T>
struct type_identity { using type = T; };
template<typename T>
using type_identity_t = typename type_identity<T>::type;
}
namespace units { namespace units {
using namespace mp::std_concepts; // todo Remove when std::concepts will arrive using namespace mp::std_concepts; // todo Remove when std::concepts will arrive

View File

@ -78,10 +78,18 @@ namespace units {
template<Exponent E> template<Exponent E>
using exp_invert_t = typename exp_invert<E>::type; using exp_invert_t = typename exp_invert<E>::type;
// dimension_traits
template<typename T>
struct dimension_traits : std::type_identity<T> {};
template<typename T>
using dimension_traits_t = typename dimension_traits<T>::type;
// dimension // dimension
template<Exponent... Es> template<Exponent... Es>
struct dimension; struct dimension : std::type_identity<dimension<Es...>> {};
// is_dimension // is_dimension
namespace detail { namespace detail {
@ -93,7 +101,20 @@ namespace units {
} // namespace detail } // namespace detail
template<typename T> template<typename T>
concept bool Dimension = detail::is_dimension<T>; concept bool Dimension = detail::is_dimension<typename T::type>;
// dim_invert
template<Dimension E>
struct dim_invert;
template<Exponent... Es>
struct dim_invert<dimension<Es...>> : std::type_identity<dimension_traits_t<dimension<exp_invert_t<Es>...>>> {};
template<Dimension D>
using dim_invert_t = typename dim_invert<typename D::type>::type;
// make_dimension // make_dimension
@ -144,12 +165,10 @@ namespace units {
struct dimension_multiply; struct dimension_multiply;
template<Exponent... E1, Exponent... E2> template<Exponent... E1, Exponent... E2>
struct dimension_multiply<dimension<E1...>, dimension<E2...>> { struct dimension_multiply<dimension<E1...>, dimension<E2...>> : std::type_identity<dimension_traits_t<make_dimension_t<E1..., E2...>>> {};
using type = make_dimension_t<E1..., E2...>;
};
template<Dimension D1, Dimension D2> template<Dimension D1, Dimension D2>
using dimension_multiply_t = typename dimension_multiply<D1, D2>::type; using dimension_multiply_t = typename dimension_multiply<typename D1::type, typename D2::type>::type;
// dimension_divide // dimension_divide
@ -162,6 +181,6 @@ namespace units {
}; };
template<Dimension D1, Dimension D2> template<Dimension D1, Dimension D2>
using dimension_divide_t = typename dimension_divide<D1, D2>::type; using dimension_divide_t = typename dimension_divide<typename D1::type, typename D2::type>::type;
} // namespace units } // namespace units

View File

@ -254,14 +254,14 @@ namespace units {
return ret(lhs.count() * rhs.count()); return ret(lhs.count() * rhs.count());
} }
template<Number Rep1, Exponent... E, Unit U, Number Rep2> template<Number Rep1, Dimension D, Unit U, Number Rep2>
quantity<dimension<exp_invert_t<E>...>, unit<dimension<exp_invert_t<E>...>, std::ratio<U::ratio::den, U::ratio::num>>, std::common_type_t<Rep1, Rep2>> quantity<dim_invert_t<D>, unit<dim_invert_t<D>, std::ratio<U::ratio::den, U::ratio::num>>, std::common_type_t<Rep1, Rep2>>
constexpr operator/(const Rep1& v, constexpr operator/(const Rep1& v,
const quantity<dimension<E...>, U, Rep2>& q) const quantity<D, U, Rep2>& q)
{ {
using dim = dimension<exp_invert_t<E>...>; using dim = dim_invert_t<D>;
using ret = quantity<dim, unit<dim, std::ratio<U::ratio::den, U::ratio::num>>, std::common_type_t<Rep1, Rep2>>; using ret = quantity<dim, unit<dim, std::ratio<U::ratio::den, U::ratio::num>>, std::common_type_t<Rep1, Rep2>>;
using den = quantity<dimension<E...>, U, std::common_type_t<Rep1, Rep2>>; using den = quantity<D, U, std::common_type_t<Rep1, Rep2>>;
return ret(v / den(q).count()); return ret(v / den(q).count());
} }

View File

@ -27,7 +27,6 @@
namespace units { namespace units {
using dimension_frequency = make_dimension_t<exp<base_dim_time, -1>>;
using millihertz = unit<dimension_frequency, std::milli>; using millihertz = unit<dimension_frequency, std::milli>;
using hertz = unit<dimension_frequency, std::ratio<1>>; using hertz = unit<dimension_frequency, std::ratio<1>>;
@ -35,6 +34,8 @@ namespace units {
using megahertz = unit<dimension_frequency, std::mega>; using megahertz = unit<dimension_frequency, std::mega>;
using gigahertz = unit<dimension_frequency, std::giga>; using gigahertz = unit<dimension_frequency, std::giga>;
using terahertz = unit<dimension_frequency, std::tera>; using terahertz = unit<dimension_frequency, std::tera>;
struct dimension_frequency : make_dimension_t<exp<base_dim_time, -1>> {};
template<> struct dimension_traits<typename dimension_frequency::type> : std::type_identity<dimension_frequency> {};
template<Unit U = hertz, Number Rep = std::intmax_t> template<Unit U = hertz, Number Rep = std::intmax_t>
using frequency = quantity<dimension_frequency, U, Rep>; using frequency = quantity<dimension_frequency, U, Rep>;

View File

@ -27,7 +27,8 @@
namespace units { namespace units {
using dimension_length = make_dimension_t<exp<base_dim_length, 1>>; struct dimension_length : make_dimension_t<exp<base_dim_length, 1>> {};
template<> struct dimension_traits<typename dimension_length::type> : std::type_identity<dimension_length> {};
using millimeter = unit<dimension_length, std::milli>; using millimeter = unit<dimension_length, std::milli>;
using centimeter = unit<dimension_length, std::ratio<1, 100>>; using centimeter = unit<dimension_length, std::ratio<1, 100>>;

View File

@ -27,14 +27,15 @@
namespace units { namespace units {
using dimension_time = make_dimension_t<exp<base_dim_time, 1>>;
using nanosecond = unit<dimension_time, std::nano>; using nanosecond = unit<dimension_time, std::nano>;
using microsecond = unit<dimension_time, std::micro>; using microsecond = unit<dimension_time, std::micro>;
using millisecond = unit<dimension_time, std::milli>; using millisecond = unit<dimension_time, std::milli>;
using second = unit<dimension_time, std::ratio<1>>; using second = unit<dimension_time, std::ratio<1>>;
using minute = unit<dimension_time, std::ratio<60>>; using minute = unit<dimension_time, std::ratio<60>>;
using hour = unit<dimension_time, std::ratio<3600>>; using hour = unit<dimension_time, std::ratio<3600>>;
struct dimension_time : make_dimension_t<exp<base_dim_time, 1>> {};
template<> struct dimension_traits<typename dimension_time::type> : std::type_identity<dimension_time> {};
template<Unit U = second, Number Rep = std::intmax_t> template<Unit U = second, Number Rep = std::intmax_t>
using time = quantity<dimension_time, U, Rep>; using time = quantity<dimension_time, U, Rep>;

View File

@ -28,7 +28,8 @@
namespace units { namespace units {
using dimension_velocity = make_dimension_t<exp<base_dim_length, 1>, exp<base_dim_time, -1>>; struct dimension_velocity : make_dimension_t<exp<base_dim_length, 1>, exp<base_dim_time, -1>> {};
template<> struct dimension_traits<typename dimension_velocity::type> : std::type_identity<dimension_velocity> {};
using meter_per_second = unit<dimension_velocity, std::ratio<1>>; using meter_per_second = unit<dimension_velocity, std::ratio<1>>;
using kilometer_per_hour = unit<dimension_velocity, std::ratio<1000, 3600>>; using kilometer_per_hour = unit<dimension_velocity, std::ratio<1000, 3600>>;