mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-04 12:54:25 +02:00
refactor: std::chrono
support refactored for V2
This commit is contained in:
@@ -23,35 +23,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <units/customization_points.h>
|
||||
// IWYU pragma: begin_exports
|
||||
#include <units/isq/si/time.h>
|
||||
#include <units/point_origin.h>
|
||||
#include <units/isq/space_and_time.h>
|
||||
#include <units/si/prefixes.h>
|
||||
#include <units/si/units.h>
|
||||
#include <chrono>
|
||||
// IWYU pragma: end_exports
|
||||
|
||||
namespace units {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename Period>
|
||||
[[nodiscard]] inline consteval auto time_unit_from_chrono_period()
|
||||
{
|
||||
using namespace si;
|
||||
|
||||
if constexpr (is_same_v<Period, std::chrono::nanoseconds::period>)
|
||||
return nano<second>;
|
||||
else if constexpr (is_same_v<Period, std::chrono::microseconds::period>)
|
||||
return micro<second>;
|
||||
else if constexpr (is_same_v<Period, std::chrono::milliseconds::period>)
|
||||
return milli<second>;
|
||||
else if constexpr (is_same_v<Period, std::chrono::seconds::period>)
|
||||
return second;
|
||||
else if constexpr (is_same_v<Period, std::chrono::minutes::period>)
|
||||
return minute;
|
||||
else if constexpr (is_same_v<Period, std::chrono::hours::period>)
|
||||
return hour;
|
||||
else if constexpr (is_same_v<Period, std::chrono::days::period>)
|
||||
return day;
|
||||
else
|
||||
return mag<ratio{Period::num, Period::den}> * second;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename Rep, typename Period>
|
||||
struct quantity_like_traits<std::chrono::duration<Rep, Period>> {
|
||||
private:
|
||||
static constexpr auto mag = ::units::mag<ratio(Period::num, Period::den)>();
|
||||
public:
|
||||
using dimension = isq::si::dim_time;
|
||||
using unit = downcast_unit<dimension, mag>;
|
||||
static constexpr auto reference = isq::duration[detail::time_unit_from_chrono_period<Period>()];
|
||||
using rep = Rep;
|
||||
[[nodiscard]] static constexpr rep number(const std::chrono::duration<Rep, Period>& q) { return q.count(); }
|
||||
};
|
||||
|
||||
template<typename C>
|
||||
struct clock_origin : point_origin<isq::si::dim_time> {};
|
||||
struct chrono_point_origin : absolute_point_origin<isq::time> {
|
||||
using clock = C;
|
||||
};
|
||||
|
||||
template<typename C, typename Rep, typename Period>
|
||||
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> {
|
||||
private:
|
||||
static constexpr auto mag = ::units::mag<ratio(Period::num, Period::den)>();
|
||||
public:
|
||||
using origin = clock_origin<C>;
|
||||
using unit = downcast_unit<typename origin::dimension, mag>;
|
||||
static constexpr auto reference = isq::time[detail::time_unit_from_chrono_period<Period>()];
|
||||
static constexpr auto point_origin = chrono_point_origin<C>{};
|
||||
using rep = Rep;
|
||||
[[nodiscard]] static constexpr auto relative(const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp)
|
||||
{
|
||||
@@ -59,42 +80,24 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
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)
|
||||
template<quantity_of<isq::time> Q>
|
||||
[[nodiscard]] constexpr auto to_chrono_duration(const Q& q)
|
||||
{
|
||||
gsl_Expects(v > 0);
|
||||
std::intmax_t res = 1;
|
||||
for (std::intmax_t i = 0; i < v; i++) res *= 10;
|
||||
return res;
|
||||
constexpr auto canonical = detail::get_canonical_unit(Q::unit);
|
||||
constexpr ratio r = as_ratio(canonical.mag);
|
||||
return std::chrono::duration<typename Q::rep, std::ratio<r.num, r.den>>{q.number()};
|
||||
}
|
||||
|
||||
template<ratio R>
|
||||
constexpr auto to_std_ratio_impl()
|
||||
template<quantity_point_of<isq::time> QP>
|
||||
requires is_specialization_of<std::remove_const_t<decltype(QP::absolute_point_origin)>, chrono_point_origin>
|
||||
[[nodiscard]] constexpr auto to_chrono_time_point(const QP& qp)
|
||||
{
|
||||
return std::ratio<R.num, R.den>{};
|
||||
}
|
||||
|
||||
} // 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<typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto to_std_duration(const quantity<isq::si::dim_time, U, Rep>& q)
|
||||
{
|
||||
return std::chrono::duration<Rep, to_std_ratio<as_ratio(U::mag)>>(q.number());
|
||||
}
|
||||
|
||||
template<typename C, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto to_std_time_point(const quantity_point<clock_origin<C>, U, Rep>& qp)
|
||||
{
|
||||
using ret_type = std::chrono::time_point<C, std::chrono::duration<Rep, to_std_ratio<as_ratio(U::mag)>>>;
|
||||
return ret_type(to_std_duration(qp.relative()));
|
||||
using clock = TYPENAME decltype(QP::absolute_point_origin)::clock;
|
||||
using rep = TYPENAME QP::rep;
|
||||
constexpr auto canonical = detail::get_canonical_unit(QP::unit);
|
||||
constexpr ratio r = as_ratio(canonical.mag);
|
||||
using ret_type = std::chrono::time_point<clock, std::chrono::duration<rep, std::ratio<r.num, r.den>>>;
|
||||
return ret_type(to_std_duration(qp.absolute()));
|
||||
}
|
||||
|
||||
} // namespace units
|
||||
|
Reference in New Issue
Block a user