feat: conversion helpers from mp-units to std::chrono types added

Resolves #316
This commit is contained in:
Mateusz Pusz
2021-11-23 11:17:47 +01:00
parent 163a2502ad
commit af928dd0c7
4 changed files with 62 additions and 0 deletions

View File

@ -5,6 +5,7 @@
- refactor: `quantity` `op+()` and `op-()` reimplemented in terms of `reference` rather then `quantity` types
- feat: `std::format` support for compliant compilers added
- feat: HEP system support added (thanks [@RalphSteinhagen](https://github.com/RalphSteinhagen))
- feat: conversion helpers from `mp-units` to `std::chrono` types added
- (!) fix: add `quantity_point::origin`, like `std::chrono::time_point::clock`
- fix: account for different dimensions in `quantity_point_cast`'s constraint
- build: Minimum Conan version changed to 1.40

View File

@ -65,3 +65,26 @@ provide a deduction guide from `QuantityPointLike`::
using namespace std::chrono_literals;
static_assert((quantity_point{std::chrono::sys_seconds{1s}} + 1 * s).relative() == 2s);
Interoperability with the C++ Standard Library
----------------------------------------------
The above ``std::chrono``-specific customization points are already predefined in the ``mp-units``
library for both ``std::chrono::duration`` as well as ``std::chrono::time_point``.
They are provided in a dedicated header file::
#include <units/chrono.h>
The same header file provides additional conversion helpers from ``mp-units`` to
the C++ Standard Library types:
- an explicit conversion of `quantity` to ``std::chrono::duration``::
template<QuantityOf<isq::si::dim_time> Q>
constexpr auto to_std_duration(const Q& q);
- an alias that provides a conversion from `ratio` to ``std::ratio``::
template<ratio R>
using to_std_ratio = /* ... */

View File

@ -58,6 +58,36 @@ namespace detail {
template<typename C, typename Rep, typename Period>
inline constexpr bool is_quantity_point_like<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> = true;
constexpr std::intmax_t pow_10(std::intmax_t v)
{
gsl_Expects(v > 0);
std::intmax_t res = 1;
for(std::intmax_t i = 0; i < v; i++)
res *= 10;
return res;
}
template<ratio R>
constexpr auto to_std_ratio_impl()
{
if constexpr(R.exp == 0)
return std::ratio<R.num, R.den>{};
else if constexpr(R.exp > 0)
return std::ratio<R.num * pow_10(R.exp), R.den>{};
else
return std::ratio<R.num, R.den * pow_10(-R.exp)>{};
}
} // namespace detail
// TODO ICE below on gcc-11 when `ratio` is used instead of `auto`
template<auto R>
using to_std_ratio = decltype(detail::to_std_ratio_impl<R>());
template<QuantityOf<isq::si::dim_time> Q>
constexpr auto to_std_duration(const Q& q)
{
return std::chrono::duration<typename Q::rep, to_std_ratio<Q::unit::ratio>>(q.number());
}
} // namespace units

View File

@ -90,4 +90,12 @@ static_assert(10_q_m / quantity{2s} == 5_q_m_per_s);
static_assert(quantity_point{sys_seconds{1s}} + 1_q_s == time_point<std::chrono::system_clock, si::second>{2_q_s});
static_assert(quantity_point{sys_seconds{1s}} + 1_q_min == time_point<std::chrono::system_clock, si::second>{61_q_s});
// to_duration
static_assert(to_std_duration(1_q_s) == 1s);
static_assert(to_std_duration(2_q_h) == 2h);
static_assert(to_std_duration(3_q_ns) == 3ns);
static_assert(is_same_v<decltype(to_std_duration(1_q_s))::period, std::ratio<1>>);
static_assert(is_same_v<decltype(to_std_duration(2_q_h))::period, std::ratio<3600>>);
static_assert(is_same_v<decltype(to_std_duration(3_q_ns))::period, std::nano>);
} // namespace