upcasting renamed to downcasting

This commit is contained in:
Mateusz Pusz
2019-07-18 23:24:24 +02:00
parent 7cbeb35e17
commit 03a22cba2a
15 changed files with 94 additions and 94 deletions

View File

@@ -27,7 +27,7 @@ static_assert(10_km / 5_km == 2);
``` ```
## Requirements ## Approach
1. Safety and performance 1. Safety and performance
- strong types - strong types
@@ -89,7 +89,7 @@ or more base dimensions:
```cpp ```cpp
template<Exponent... Es> template<Exponent... Es>
struct dimension : upcast_base<dimension<Es...>> {}; struct dimension : downcast_base<dimension<Es...>> {};
``` ```
`units::Dimension` is a Concept that is satisfied by a type that is empty and publicly `units::Dimension` is a Concept that is satisfied by a type that is empty and publicly
@@ -99,7 +99,7 @@ derived from `units::dimension` class template:
template<typename T> template<typename T>
concept Dimension = concept Dimension =
std::is_empty_v<T> && std::is_empty_v<T> &&
detail::is_dimension<upcast_from<T>>; // exposition only detail::is_dimension<downcast_from<T>>; // exposition only
``` ```
#### `Exponents` #### `Exponents`
@@ -195,7 +195,7 @@ 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...>> {
using type = upcasting_traits_t<merge_dimension_t<dimension<E1...>, dimension<E2...>>>; using type = downcasting_traits_t<merge_dimension_t<dimension<E1...>, dimension<E2...>>>;
}; };
template<Dimension D1, Dimension D2> template<Dimension D1, Dimension D2>
@@ -219,7 +219,7 @@ struct merge_dimension {
```cpp ```cpp
template<Dimension D, Ratio R> template<Dimension D, Ratio R>
requires (R::num > 0) requires (R::num > 0)
struct unit : upcast_base<unit<D, R>> { struct unit : downcast_base<unit<D, R>> {
using dimension = D; using dimension = D;
using ratio = R; using ratio = R;
}; };
@@ -232,7 +232,7 @@ derived from `units::unit` class template:
template<typename T> template<typename T>
concept Unit = concept Unit =
std::is_empty_v<T> && std::is_empty_v<T> &&
detail::is_unit<upcast_from<T>>; // exposition only detail::is_unit<downcast_from<T>>; // exposition only
``` ```
### `Quantities` ### `Quantities`
@@ -268,18 +268,18 @@ public:
template<Dimension D1, Unit U1, Number Rep1, Dimension D2, Unit U2, Number Rep2> template<Dimension D1, Unit U1, Number Rep1, Dimension D2, Unit U2, Number Rep2>
requires treat_as_floating_point<std::common_type_t<Rep1, Rep2>> || std::ratio_multiply<typename U1::ratio, typename U2::ratio>::den == 1 requires treat_as_floating_point<std::common_type_t<Rep1, Rep2>> || std::ratio_multiply<typename U1::ratio, typename U2::ratio>::den == 1
quantity<dimension_multiply_t<D1, D2>, upcasting_traits_t<unit<dimension_multiply_t<D1, D2>, std::ratio_multiply<typename U1::ratio, typename U2::ratio>>>, std::common_type_t<Rep1, Rep2>> quantity<dimension_multiply_t<D1, D2>, downcasting_traits_t<unit<dimension_multiply_t<D1, D2>, std::ratio_multiply<typename U1::ratio, typename U2::ratio>>>, std::common_type_t<Rep1, Rep2>>
constexpr operator*(const quantity<D1, U1, Rep1>& lhs, constexpr operator*(const quantity<D1, U1, Rep1>& lhs,
const quantity<D2, U2, Rep2>& rhs); const quantity<D2, U2, Rep2>& rhs);
template<Number Rep1, Dimension D, Unit U, Number Rep2> template<Number Rep1, Dimension D, Unit U, Number Rep2>
quantity<dim_invert_t<D>, upcasting_traits_t<unit<dim_invert_t<D>, std::ratio<U::ratio::den, U::ratio::num>>>, std::common_type_t<Rep1, Rep2>> quantity<dim_invert_t<D>, downcasting_traits_t<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<D, U, Rep2>& q) [[expects: q != quantity<D, U, Rep2>(0)]]; const quantity<D, U, Rep2>& q) [[expects: q != quantity<D, U, Rep2>(0)]];
template<Dimension D1, Unit U1, Number Rep1, Dimension D2, Unit U2, Number Rep2> template<Dimension D1, Unit U1, Number Rep1, Dimension D2, Unit U2, Number Rep2>
requires treat_as_floating_point<std::common_type_t<Rep1, Rep2>> || std::ratio_divide<typename U1::ratio, typename U2::ratio>::den == 1 requires treat_as_floating_point<std::common_type_t<Rep1, Rep2>> || std::ratio_divide<typename U1::ratio, typename U2::ratio>::den == 1
quantity<dimension_divide_t<D1, D2>, upcasting_traits_t<unit<dimension_divide_t<D1, D2>, std::ratio_divide<typename U1::ratio, typename U2::ratio>>>, std::common_type_t<Rep1, Rep2>> quantity<dimension_divide_t<D1, D2>, downcasting_traits_t<unit<dimension_divide_t<D1, D2>, std::ratio_divide<typename U1::ratio, typename U2::ratio>>>, std::common_type_t<Rep1, Rep2>>
constexpr operator/(const quantity<D1, U1, Rep1>& lhs, constexpr operator/(const quantity<D1, U1, Rep1>& lhs,
const quantity<D2, U2, Rep2>& rhs) [[expects: rhs != quantity<D, U2, Rep2>(0)]]; const quantity<D2, U2, Rep2>& rhs) [[expects: rhs != quantity<D, U2, Rep2>(0)]];
}; };
@@ -300,7 +300,7 @@ operation and provides it directly to `units::common_quantity_t` type trait.
To explicitly force truncating conversions `quantity_cast` function is provided which is a direct To explicitly force truncating conversions `quantity_cast` function is provided which is a direct
counterpart of `std::chrono::duration_cast`. counterpart of `std::chrono::duration_cast`.
## Strong types instead of aliases, and type upcasting capability ## Strong types instead of aliases, and type downcasting capability
Most of the important design decisions in the library are dictated by the requirement of providing Most of the important design decisions in the library are dictated by the requirement of providing
the best user experience as possible. the best user experience as possible.
@@ -347,7 +347,7 @@ and
starts to be really hard to analyze or debug. starts to be really hard to analyze or debug.
That is why it was decided to provide automated upcasting capability when possible. With that the That is why it was decided to provide automated downcasting capability when possible. With that the
same code will result with such an error: same code will result with such an error:
```text ```text
@@ -383,33 +383,33 @@ and
are not arguably much easier to understand thus provide better user experience. are not arguably much easier to understand thus provide better user experience.
Upcasting capability is provided through dedicated `upcasting_traits`, a few helper aliases and by downcasting capability is provided through dedicated `downcasting_traits`, a few helper aliases and by
`base_type` member type in `upcast_base` class template. `base_type` member type in `downcast_base` class template.
```cpp ```cpp
template<Upcastable T> template<Downcastable T>
using upcast_from = T::base_type; using downcast_from = T::base_type;
template<typename T> template<typename T>
using upcast_to = std::type_identity<T>; using downcast_to = std::type_identity<T>;
template<typename T> template<typename T>
struct upcasting_traits : upcast_to<T> {}; struct downcasting_traits : downcast_to<T> {};
template<typename T> template<typename T>
using upcasting_traits_t = upcasting_traits<T>::type; using downcasting_traits_t = downcasting_traits<T>::type;
``` ```
With that the upcasting functionality is enabled by: With that the downcasting functionality is enabled by:
```cpp ```cpp
struct dimension_length : make_dimension_t<exp<base_dim_length, 1>> {}; struct dimension_length : make_dimension_t<exp<base_dim_length, 1>> {};
template<> struct upcasting_traits<upcast_from<dimension_length>> : upcast_to<dimension_length> {}; template<> struct downcasting_traits<downcast_from<dimension_length>> : downcast_to<dimension_length> {};
``` ```
```cpp ```cpp
struct kilometer : unit<dimension_length, std::kilo> {}; struct kilometer : unit<dimension_length, std::kilo> {};
template<> struct upcasting_traits<upcast_from<kilometer>> : upcast_to<kilometer> {}; template<> struct downcasting_traits<downcast_from<kilometer>> : downcast_to<kilometer> {};
``` ```
@@ -417,11 +417,11 @@ template<> struct upcasting_traits<upcast_from<kilometer>> : upcast_to<kilometer
In order to extend the library with custom dimensions the user has to: In order to extend the library with custom dimensions the user has to:
1. Create a new dimension type with the recipe of how to construct it from base dimensions and provide 1. Create a new dimension type with the recipe of how to construct it from base dimensions and provide
upcasting trait for it: downcasting trait for it:
```cpp ```cpp
struct 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 upcasting_traits<upcast_from<dimension_velocity>> : upcast_to<dimension_velocity> {}; template<> struct downcasting_traits<downcast_from<dimension_velocity>> : downcast_to<dimension_velocity> {};
``` ```
2. Provide `quantity` class template partial specialization for new dimension and provide its base type: 2. Provide `quantity` class template partial specialization for new dimension and provide its base type:
@@ -438,27 +438,27 @@ template<typename T>
concept Velocity = Quantity<T> && std::Same<typename T::dimension, dimension_velocity>; concept Velocity = Quantity<T> && std::Same<typename T::dimension, dimension_velocity>;
``` ```
4. Define units and provide upcasting traits for them: 4. Define units and provide downcasting traits for them:
- base unit - base unit
```cpp ```cpp
struct meter : unit<dimension_length, std::ratio<1>> {}; struct meter : unit<dimension_length, std::ratio<1>> {};
template<> struct upcasting_traits<upcast_from<meter>> : upcast_to<meter> {}; template<> struct downcasting_traits<downcast_from<meter>> : downcast_to<meter> {};
``` ```
- units with prefixes - units with prefixes
```cpp ```cpp
struct kilometer : kilo<meter> {}; struct kilometer : kilo<meter> {};
template<> struct upcasting_traits<upcast_from<kilometer>> : upcast_to<kilometer> {}; template<> struct downcasting_traits<downcast_from<kilometer>> : downcast_to<kilometer> {};
``` ```
- derived units - derived units
```cpp ```cpp
struct kilometer_per_hour : derived_unit<dimension_velocity, kilometer, hour> {}; struct kilometer_per_hour : derived_unit<dimension_velocity, kilometer, hour> {};
template<> struct upcasting_traits<upcast_from<kilometer_per_hour>> : upcast_to<kilometer_per_hour> {}; template<> struct downcasting_traits<downcast_from<kilometer_per_hour>> : downcast_to<kilometer_per_hour> {};
``` ```
5. Provide user-defined literals for the most important units: 5. Provide user-defined literals for the most important units:
@@ -507,7 +507,7 @@ Additionally, it should make the error logs even shorter thus easier to understa
1. Should we ensure that dimension is always a result of `make_dimension`? How to do it? 1. Should we ensure that dimension is always a result of `make_dimension`? How to do it?
2. Should we provide strong types and upcasting_traits for `quantity` type? 2. Should we provide strong types and downcasting_traits for `quantity` type?
In such a case all the operators have to be provided to a child class. Or maybe use CRTP? In such a case all the operators have to be provided to a child class. Or maybe use CRTP?

View File

@@ -27,7 +27,7 @@
namespace units { namespace units {
struct dimension_area : make_dimension_t<exp<base_dim_length, 2>> {}; struct dimension_area : make_dimension_t<exp<base_dim_length, 2>> {};
template<> struct upcasting_traits<upcast_from<dimension_area>> : upcast_to<dimension_area> {}; template<> struct downcasting_traits<downcast_from<dimension_area>> : downcast_to<dimension_area> {};
template<typename T> template<typename T>
concept bool Area = Quantity<T> && std::Same<typename T::dimension, dimension_area>; concept bool Area = Quantity<T> && std::Same<typename T::dimension, dimension_area>;
@@ -36,19 +36,19 @@ namespace units {
using area = quantity<dimension_area, U, Rep>; using area = quantity<dimension_area, U, Rep>;
struct square_millimeter : derived_unit<dimension_area, millimeter> {}; struct square_millimeter : derived_unit<dimension_area, millimeter> {};
template<> struct upcasting_traits<upcast_from<square_millimeter>> : upcast_to<square_millimeter> {}; template<> struct downcasting_traits<downcast_from<square_millimeter>> : downcast_to<square_millimeter> {};
struct square_centimeter : derived_unit<dimension_area, centimeter> {}; struct square_centimeter : derived_unit<dimension_area, centimeter> {};
template<> struct upcasting_traits<upcast_from<square_centimeter>> : upcast_to<square_centimeter> {}; template<> struct downcasting_traits<downcast_from<square_centimeter>> : downcast_to<square_centimeter> {};
struct square_meter : derived_unit<dimension_area, meter> {}; struct square_meter : derived_unit<dimension_area, meter> {};
template<> struct upcasting_traits<upcast_from<square_meter>> : upcast_to<square_meter> {}; template<> struct downcasting_traits<downcast_from<square_meter>> : downcast_to<square_meter> {};
struct square_kilometer : derived_unit<dimension_area, kilometer, meter> {}; struct square_kilometer : derived_unit<dimension_area, kilometer, meter> {};
template<> struct upcasting_traits<upcast_from<square_kilometer>> : upcast_to<square_kilometer> {}; template<> struct downcasting_traits<downcast_from<square_kilometer>> : downcast_to<square_kilometer> {};
struct square_foot : derived_unit<dimension_area, foot> {}; struct square_foot : derived_unit<dimension_area, foot> {};
template<> struct upcasting_traits<upcast_from<square_foot>> : upcast_to<square_foot> {}; template<> struct downcasting_traits<downcast_from<square_foot>> : downcast_to<square_foot> {};
inline namespace literals { inline namespace literals {

View File

@@ -28,27 +28,27 @@
namespace units { namespace units {
template<typename BaseType> template<typename BaseType>
struct upcast_base { struct downcast_base {
using base_type = BaseType; using base_type = BaseType;
}; };
template<typename T> template<typename T>
concept bool Upcastable = concept bool Downcastable =
requires { requires {
typename T::base_type; typename T::base_type;
} && } &&
std::DerivedFrom<T, upcast_base<typename T::base_type>>; std::DerivedFrom<T, downcast_base<typename T::base_type>>;
template<Upcastable T> template<Downcastable T>
using upcast_from = T::base_type; using downcast_from = T::base_type;
template<Upcastable T> template<Downcastable T>
using upcast_to = std::type_identity<T>; using downcast_to = std::type_identity<T>;
template<Upcastable T> template<Downcastable T>
struct upcasting_traits : upcast_to<T> {}; struct downcasting_traits : downcast_to<T> {};
template<Upcastable T> template<Downcastable T>
using upcasting_traits_t = upcasting_traits<T>::type; using downcasting_traits_t = downcasting_traits<T>::type;
} // namespace units } // namespace units

View File

@@ -28,7 +28,7 @@
namespace units { namespace units {
struct dimension_current : make_dimension_t<exp<base_dim_current, 1>> {}; struct dimension_current : make_dimension_t<exp<base_dim_current, 1>> {};
template<> struct upcasting_traits<upcast_from<dimension_current>> : upcast_to<dimension_current> {}; template<> struct downcasting_traits<downcast_from<dimension_current>> : downcast_to<dimension_current> {};
template<typename T> template<typename T>
concept bool Current = Quantity<T> && std::Same<typename T::dimension, dimension_current>; concept bool Current = Quantity<T> && std::Same<typename T::dimension, dimension_current>;
@@ -37,7 +37,7 @@ namespace units {
using current = quantity<dimension_current, U, Rep>; using current = quantity<dimension_current, U, Rep>;
struct ampere : unit<dimension_current> {}; struct ampere : unit<dimension_current> {};
template<> struct upcasting_traits<upcast_from<ampere>> : upcast_to<ampere> {}; template<> struct downcasting_traits<downcast_from<ampere>> : downcast_to<ampere> {};
inline namespace literals { inline namespace literals {

View File

@@ -23,7 +23,7 @@
#pragma once #pragma once
#include <units/bits/type_list.h> #include <units/bits/type_list.h>
#include <units/bits/upcasting.h> #include <units/bits/downcasting.h>
namespace units { namespace units {
@@ -81,7 +81,7 @@ namespace units {
// dimension // dimension
template<Exponent... Es> template<Exponent... Es>
struct dimension : upcast_base<dimension<Es...>> {}; struct dimension : downcast_base<dimension<Es...>> {};
// is_dimension // is_dimension
namespace detail { namespace detail {
@@ -97,7 +97,7 @@ namespace units {
template<typename T> template<typename T>
concept bool Dimension = concept bool Dimension =
std::is_empty_v<T> && std::is_empty_v<T> &&
detail::is_dimension<upcast_from<T>>; detail::is_dimension<downcast_from<T>>;
// dim_invert // dim_invert
@@ -106,7 +106,7 @@ namespace units {
struct dim_invert; struct dim_invert;
template<Exponent... Es> template<Exponent... Es>
struct dim_invert<dimension<Es...>> : std::type_identity<upcasting_traits_t<dimension<exp_invert_t<Es>...>>> {}; struct dim_invert<dimension<Es...>> : std::type_identity<downcasting_traits_t<dimension<exp_invert_t<Es>...>>> {};
template<Dimension D> template<Dimension D>
using dim_invert_t = dim_invert<typename D::base_type>::type; using dim_invert_t = dim_invert<typename D::base_type>::type;
@@ -168,7 +168,7 @@ 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...>> : std::type_identity<upcasting_traits_t<merge_dimension_t<dimension<E1...>, dimension<E2...>>>> {}; struct dimension_multiply<dimension<E1...>, dimension<E2...>> : std::type_identity<downcasting_traits_t<merge_dimension_t<dimension<E1...>, dimension<E2...>>>> {};
template<Dimension D1, Dimension D2> template<Dimension D1, Dimension D2>
using dimension_multiply_t = dimension_multiply<typename D1::base_type, typename D2::base_type>::type; using dimension_multiply_t = dimension_multiply<typename D1::base_type, typename D2::base_type>::type;

View File

@@ -28,7 +28,7 @@
namespace units { namespace units {
struct dimension_frequency : make_dimension_t<exp<base_dim_time, -1>> {}; struct dimension_frequency : make_dimension_t<exp<base_dim_time, -1>> {};
template<> struct upcasting_traits<upcast_from<dimension_frequency>> : upcast_to<dimension_frequency> {}; template<> struct downcasting_traits<downcast_from<dimension_frequency>> : downcast_to<dimension_frequency> {};
template<typename T> template<typename T>
concept bool Frequency = Quantity<T> && std::Same<typename T::dimension, dimension_frequency>; concept bool Frequency = Quantity<T> && std::Same<typename T::dimension, dimension_frequency>;
@@ -37,22 +37,22 @@ namespace units {
using frequency = quantity<dimension_frequency, U, Rep>; using frequency = quantity<dimension_frequency, U, Rep>;
struct hertz : derived_unit<dimension_frequency, second> {}; struct hertz : derived_unit<dimension_frequency, second> {};
template<> struct upcasting_traits<upcast_from<hertz>> : upcast_to<hertz> {}; template<> struct downcasting_traits<downcast_from<hertz>> : downcast_to<hertz> {};
struct millihertz : milli<hertz> {}; struct millihertz : milli<hertz> {};
template<> struct upcasting_traits<upcast_from<millihertz>> : upcast_to<millihertz> {}; template<> struct downcasting_traits<downcast_from<millihertz>> : downcast_to<millihertz> {};
struct kilohertz : kilo<hertz> {}; struct kilohertz : kilo<hertz> {};
template<> struct upcasting_traits<upcast_from<kilohertz>> : upcast_to<kilohertz> {}; template<> struct downcasting_traits<downcast_from<kilohertz>> : downcast_to<kilohertz> {};
struct megahertz : mega<hertz> {}; struct megahertz : mega<hertz> {};
template<> struct upcasting_traits<upcast_from<megahertz>> : upcast_to<megahertz> {}; template<> struct downcasting_traits<downcast_from<megahertz>> : downcast_to<megahertz> {};
struct gigahertz : giga<hertz> {}; struct gigahertz : giga<hertz> {};
template<> struct upcasting_traits<upcast_from<gigahertz>> : upcast_to<gigahertz> {}; template<> struct downcasting_traits<downcast_from<gigahertz>> : downcast_to<gigahertz> {};
struct terahertz : tera<hertz> {}; struct terahertz : tera<hertz> {};
template<> struct upcasting_traits<upcast_from<terahertz>> : upcast_to<terahertz> {}; template<> struct downcasting_traits<downcast_from<terahertz>> : downcast_to<terahertz> {};
inline namespace literals { inline namespace literals {

View File

@@ -28,7 +28,7 @@
namespace units { namespace units {
struct dimension_length : make_dimension_t<exp<base_dim_length, 1>> {}; struct dimension_length : make_dimension_t<exp<base_dim_length, 1>> {};
template<> struct upcasting_traits<upcast_from<dimension_length>> : upcast_to<dimension_length> {}; template<> struct downcasting_traits<downcast_from<dimension_length>> : downcast_to<dimension_length> {};
template<typename T> template<typename T>
concept bool Length = Quantity<T> && std::Same<typename T::dimension, dimension_length>; concept bool Length = Quantity<T> && std::Same<typename T::dimension, dimension_length>;
@@ -38,16 +38,16 @@ namespace units {
// SI units // SI units
struct meter : unit<dimension_length> {}; struct meter : unit<dimension_length> {};
template<> struct upcasting_traits<upcast_from<meter>> : upcast_to<meter> {}; template<> struct downcasting_traits<downcast_from<meter>> : downcast_to<meter> {};
struct millimeter : milli<meter> {}; struct millimeter : milli<meter> {};
template<> struct upcasting_traits<upcast_from<millimeter>> : upcast_to<millimeter> {}; template<> struct downcasting_traits<downcast_from<millimeter>> : downcast_to<millimeter> {};
struct centimeter : centi<meter> {}; struct centimeter : centi<meter> {};
template<> struct upcasting_traits<upcast_from<centimeter>> : upcast_to<centimeter> {}; template<> struct downcasting_traits<downcast_from<centimeter>> : downcast_to<centimeter> {};
struct kilometer : kilo<meter> {}; struct kilometer : kilo<meter> {};
template<> struct upcasting_traits<upcast_from<kilometer>> : upcast_to<kilometer> {}; template<> struct downcasting_traits<downcast_from<kilometer>> : downcast_to<kilometer> {};
inline namespace literals { inline namespace literals {
@@ -71,16 +71,16 @@ namespace units {
// US customary units // US customary units
struct yard : unit<dimension_length, ratio<9'144, 10'000>> {}; struct yard : unit<dimension_length, ratio<9'144, 10'000>> {};
template<> struct upcasting_traits<upcast_from<yard>> : upcast_to<yard> {}; template<> struct downcasting_traits<downcast_from<yard>> : downcast_to<yard> {};
struct foot : unit<dimension_length, ratio_multiply<ratio<1, 3>, yard::ratio>> {}; struct foot : unit<dimension_length, ratio_multiply<ratio<1, 3>, yard::ratio>> {};
template<> struct upcasting_traits<upcast_from<foot>> : upcast_to<foot> {}; template<> struct downcasting_traits<downcast_from<foot>> : downcast_to<foot> {};
struct inch : unit<dimension_length, ratio_multiply<ratio<1, 12>, foot::ratio>> {}; struct inch : unit<dimension_length, ratio_multiply<ratio<1, 12>, foot::ratio>> {};
template<> struct upcasting_traits<upcast_from<inch>> : upcast_to<inch> {}; template<> struct downcasting_traits<downcast_from<inch>> : downcast_to<inch> {};
struct mile : unit<dimension_length, ratio_multiply<ratio<1'760>, yard::ratio>> {}; struct mile : unit<dimension_length, ratio_multiply<ratio<1'760>, yard::ratio>> {};
template<> struct upcasting_traits<upcast_from<mile>> : upcast_to<mile> {}; template<> struct downcasting_traits<downcast_from<mile>> : downcast_to<mile> {};
inline namespace literals { inline namespace literals {

View File

@@ -28,7 +28,7 @@
namespace units { namespace units {
struct dimension_luminous_intensity : make_dimension_t<exp<base_dim_luminous_intensity, 1>> {}; struct dimension_luminous_intensity : make_dimension_t<exp<base_dim_luminous_intensity, 1>> {};
template<> struct upcasting_traits<upcast_from<dimension_luminous_intensity>> : upcast_to<dimension_luminous_intensity> {}; template<> struct downcasting_traits<downcast_from<dimension_luminous_intensity>> : downcast_to<dimension_luminous_intensity> {};
template<typename T> template<typename T>
concept bool LuminousIntensity = Quantity<T> && std::Same<typename T::dimension, dimension_luminous_intensity>; concept bool LuminousIntensity = Quantity<T> && std::Same<typename T::dimension, dimension_luminous_intensity>;
@@ -37,7 +37,7 @@ namespace units {
using luminous_intensity = quantity<dimension_luminous_intensity, U, Rep>; using luminous_intensity = quantity<dimension_luminous_intensity, U, Rep>;
struct candela : unit<dimension_luminous_intensity> {}; struct candela : unit<dimension_luminous_intensity> {};
template<> struct upcasting_traits<upcast_from<candela>> : upcast_to<candela> {}; template<> struct downcasting_traits<downcast_from<candela>> : downcast_to<candela> {};
inline namespace literals { inline namespace literals {

View File

@@ -28,7 +28,7 @@
namespace units { namespace units {
struct dimension_mass : make_dimension_t<exp<base_dim_mass, 1>> {}; struct dimension_mass : make_dimension_t<exp<base_dim_mass, 1>> {};
template<> struct upcasting_traits<upcast_from<dimension_mass>> : upcast_to<dimension_mass> {}; template<> struct downcasting_traits<downcast_from<dimension_mass>> : downcast_to<dimension_mass> {};
template<typename T> template<typename T>
concept bool Mass = Quantity<T> && std::Same<typename T::dimension, dimension_mass>; concept bool Mass = Quantity<T> && std::Same<typename T::dimension, dimension_mass>;
@@ -37,10 +37,10 @@ namespace units {
using mass = quantity<dimension_mass, U, Rep>; using mass = quantity<dimension_mass, U, Rep>;
struct gram : unit<dimension_mass, ratio<1, 1000>> {}; struct gram : unit<dimension_mass, ratio<1, 1000>> {};
template<> struct upcasting_traits<upcast_from<gram>> : upcast_to<gram> {}; template<> struct downcasting_traits<downcast_from<gram>> : downcast_to<gram> {};
struct kilogram : kilo<gram> {}; struct kilogram : kilo<gram> {};
template<> struct upcasting_traits<upcast_from<kilogram>> : upcast_to<kilogram> {}; template<> struct downcasting_traits<downcast_from<kilogram>> : downcast_to<kilogram> {};
inline namespace literals { inline namespace literals {

View File

@@ -67,7 +67,7 @@ namespace units {
template<Dimension D, Unit U1, Scalar Rep1, Unit U2, Scalar Rep2, Scalar Rep> template<Dimension D, Unit U1, Scalar Rep1, Unit U2, Scalar Rep2, Scalar Rep>
struct common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, Rep> { struct common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, Rep> {
using type = quantity<D, upcasting_traits_t<unit<D, common_ratio<typename U1::ratio, typename U2::ratio>>>, Rep>; using type = quantity<D, downcasting_traits_t<unit<D, common_ratio<typename U1::ratio, typename U2::ratio>>>, Rep>;
}; };
template<Quantity Q1, Quantity Q2, Scalar Rep = std::common_type_t<typename Q1::rep, typename Q2::rep>> template<Quantity Q1, Quantity Q2, Scalar Rep = std::common_type_t<typename Q1::rep, typename Q2::rep>>
@@ -284,7 +284,7 @@ namespace units {
{ {
using dim = dimension_multiply_t<D1, D2>; using dim = dimension_multiply_t<D1, D2>;
using common_rep = decltype(lhs.count() * rhs.count()); using common_rep = decltype(lhs.count() * rhs.count());
using ret = quantity<dim, upcasting_traits_t<unit<dim, ratio_multiply<typename U1::ratio, typename U2::ratio>>>, common_rep>; using ret = quantity<dim, downcasting_traits_t<unit<dim, ratio_multiply<typename U1::ratio, typename U2::ratio>>>, common_rep>;
return ret(lhs.count() * rhs.count()); return ret(lhs.count() * rhs.count());
} }
@@ -298,7 +298,7 @@ namespace units {
using dim = dim_invert_t<D>; using dim = dim_invert_t<D>;
using common_rep = decltype(v / q.count()); using common_rep = decltype(v / q.count());
using ret = quantity<dim, upcasting_traits_t<unit<dim, ratio<U::ratio::den, U::ratio::num>>>, common_rep>; using ret = quantity<dim, downcasting_traits_t<unit<dim, ratio<U::ratio::den, U::ratio::num>>>, common_rep>;
using den = quantity<D, U, common_rep>; using den = quantity<D, U, common_rep>;
return ret(v / den(q).count()); return ret(v / den(q).count());
} }
@@ -337,7 +337,7 @@ namespace units {
using common_rep = decltype(lhs.count() / rhs.count()); using common_rep = decltype(lhs.count() / rhs.count());
using dim = dimension_divide_t<D1, D2>; using dim = dimension_divide_t<D1, D2>;
using ret = quantity<dim, upcasting_traits_t<unit<dim, ratio_divide<typename U1::ratio, typename U2::ratio>>>, common_rep>; using ret = quantity<dim, downcasting_traits_t<unit<dim, ratio_divide<typename U1::ratio, typename U2::ratio>>>, common_rep>;
return ret(lhs.count() / rhs.count()); return ret(lhs.count() / rhs.count());
} }

View File

@@ -28,7 +28,7 @@
namespace units { namespace units {
struct dimension_substance : make_dimension_t<exp<base_dim_substance, 1>> {}; struct dimension_substance : make_dimension_t<exp<base_dim_substance, 1>> {};
template<> struct upcasting_traits<upcast_from<dimension_substance>> : upcast_to<dimension_substance> {}; template<> struct downcasting_traits<downcast_from<dimension_substance>> : downcast_to<dimension_substance> {};
template<typename T> template<typename T>
concept bool Substance = Quantity<T> && std::Same<typename T::dimension, dimension_substance>; concept bool Substance = Quantity<T> && std::Same<typename T::dimension, dimension_substance>;
@@ -37,7 +37,7 @@ namespace units {
using substance = quantity<dimension_substance, U, Rep>; using substance = quantity<dimension_substance, U, Rep>;
struct mole : unit<dimension_substance> {}; struct mole : unit<dimension_substance> {};
template<> struct upcasting_traits<upcast_from<mole>> : upcast_to<mole> {}; template<> struct downcasting_traits<downcast_from<mole>> : downcast_to<mole> {};
inline namespace literals { inline namespace literals {

View File

@@ -28,7 +28,7 @@
namespace units { namespace units {
struct dimension_temperature : make_dimension_t<exp<base_dim_temperature, 1>> {}; struct dimension_temperature : make_dimension_t<exp<base_dim_temperature, 1>> {};
template<> struct upcasting_traits<upcast_from<dimension_temperature>> : upcast_to<dimension_temperature> {}; template<> struct downcasting_traits<downcast_from<dimension_temperature>> : downcast_to<dimension_temperature> {};
template<typename T> template<typename T>
concept bool ThermodynamicTemperature = Quantity<T> && std::Same<typename T::dimension, dimension_temperature>; concept bool ThermodynamicTemperature = Quantity<T> && std::Same<typename T::dimension, dimension_temperature>;
@@ -37,7 +37,7 @@ namespace units {
using temperature = quantity<dimension_temperature, U, Rep>; using temperature = quantity<dimension_temperature, U, Rep>;
struct kelvin : unit<dimension_temperature> {}; struct kelvin : unit<dimension_temperature> {};
template<> struct upcasting_traits<upcast_from<kelvin>> : upcast_to<kelvin> {}; template<> struct downcasting_traits<downcast_from<kelvin>> : downcast_to<kelvin> {};
inline namespace literals { inline namespace literals {

View File

@@ -28,7 +28,7 @@
namespace units { namespace units {
struct dimension_time : make_dimension_t<exp<base_dim_time, 1>> {}; struct dimension_time : make_dimension_t<exp<base_dim_time, 1>> {};
template<> struct upcasting_traits<upcast_from<dimension_time>> : upcast_to<dimension_time> {}; template<> struct downcasting_traits<downcast_from<dimension_time>> : downcast_to<dimension_time> {};
template<typename T> template<typename T>
concept bool Time = Quantity<T> && std::Same<typename T::dimension, dimension_time>; concept bool Time = Quantity<T> && std::Same<typename T::dimension, dimension_time>;
@@ -37,22 +37,22 @@ namespace units {
using time = quantity<dimension_time, U, Rep>; using time = quantity<dimension_time, U, Rep>;
struct second : unit<dimension_time> {}; struct second : unit<dimension_time> {};
template<> struct upcasting_traits<upcast_from<second>> : upcast_to<second> {}; template<> struct downcasting_traits<downcast_from<second>> : downcast_to<second> {};
struct nanosecond : nano<second> {}; struct nanosecond : nano<second> {};
template<> struct upcasting_traits<upcast_from<nanosecond>> : upcast_to<nanosecond> {}; template<> struct downcasting_traits<downcast_from<nanosecond>> : downcast_to<nanosecond> {};
struct microsecond : micro<second> {}; struct microsecond : micro<second> {};
template<> struct upcasting_traits<upcast_from<microsecond>> : upcast_to<microsecond> {}; template<> struct downcasting_traits<downcast_from<microsecond>> : downcast_to<microsecond> {};
struct millisecond : milli<second> {}; struct millisecond : milli<second> {};
template<> struct upcasting_traits<upcast_from<millisecond>> : upcast_to<millisecond> {}; template<> struct downcasting_traits<downcast_from<millisecond>> : downcast_to<millisecond> {};
struct minute : unit<dimension_time, ratio<60>> {}; struct minute : unit<dimension_time, ratio<60>> {};
template<> struct upcasting_traits<upcast_from<minute>> : upcast_to<minute> {}; template<> struct downcasting_traits<downcast_from<minute>> : downcast_to<minute> {};
struct hour : unit<dimension_time, ratio<3600>> {}; struct hour : unit<dimension_time, ratio<3600>> {};
template<> struct upcasting_traits<upcast_from<hour>> : upcast_to<hour> {}; template<> struct downcasting_traits<downcast_from<hour>> : downcast_to<hour> {};
inline namespace literals { inline namespace literals {

View File

@@ -30,7 +30,7 @@ namespace units {
template<Dimension D, Ratio R = ratio<1>> template<Dimension D, Ratio R = ratio<1>>
requires (R::num > 0) requires (R::num > 0)
struct unit : upcast_base<unit<D, R>> { struct unit : downcast_base<unit<D, R>> {
using dimension = D; using dimension = D;
using ratio = R; using ratio = R;
}; };
@@ -50,7 +50,7 @@ namespace units {
template<typename T> template<typename T>
concept bool Unit = concept bool Unit =
std::is_empty_v<T> && std::is_empty_v<T> &&
detail::is_unit<upcast_from<T>>; detail::is_unit<downcast_from<T>>;
// derived_unit // derived_unit

View File

@@ -28,7 +28,7 @@
namespace units { namespace units {
struct 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 upcasting_traits<upcast_from<dimension_velocity>> : upcast_to<dimension_velocity> {}; template<> struct downcasting_traits<downcast_from<dimension_velocity>> : downcast_to<dimension_velocity> {};
template<typename T> template<typename T>
concept bool Velocity = Quantity<T> && std::Same<typename T::dimension, dimension_velocity>; concept bool Velocity = Quantity<T> && std::Same<typename T::dimension, dimension_velocity>;
@@ -37,13 +37,13 @@ namespace units {
using velocity = quantity<dimension_velocity, U, Rep>; using velocity = quantity<dimension_velocity, U, Rep>;
struct meter_per_second : derived_unit<dimension_velocity, meter, second> {}; struct meter_per_second : derived_unit<dimension_velocity, meter, second> {};
template<> struct upcasting_traits<upcast_from<meter_per_second>> : upcast_to<meter_per_second> {}; template<> struct downcasting_traits<downcast_from<meter_per_second>> : downcast_to<meter_per_second> {};
struct kilometer_per_hour : derived_unit<dimension_velocity, kilometer, hour> {}; struct kilometer_per_hour : derived_unit<dimension_velocity, kilometer, hour> {};
template<> struct upcasting_traits<upcast_from<kilometer_per_hour>> : upcast_to<kilometer_per_hour> {}; template<> struct downcasting_traits<downcast_from<kilometer_per_hour>> : downcast_to<kilometer_per_hour> {};
struct mile_per_hour : derived_unit<dimension_velocity, mile, hour> {}; struct mile_per_hour : derived_unit<dimension_velocity, mile, hour> {};
template<> struct upcasting_traits<upcast_from<mile_per_hour>> : upcast_to<mile_per_hour> {}; template<> struct downcasting_traits<downcast_from<mile_per_hour>> : downcast_to<mile_per_hour> {};
inline namespace literals { inline namespace literals {