mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-04 20:54:28 +02:00
refactor: std::chrono
support refactored for V2
This commit is contained in:
@@ -23,35 +23,56 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/customization_points.h>
|
#include <units/customization_points.h>
|
||||||
// IWYU pragma: begin_exports
|
#include <units/isq/space_and_time.h>
|
||||||
#include <units/isq/si/time.h>
|
#include <units/si/prefixes.h>
|
||||||
#include <units/point_origin.h>
|
#include <units/si/units.h>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
// IWYU pragma: end_exports
|
|
||||||
|
|
||||||
namespace units {
|
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>
|
template<typename Rep, typename Period>
|
||||||
struct quantity_like_traits<std::chrono::duration<Rep, Period>> {
|
struct quantity_like_traits<std::chrono::duration<Rep, Period>> {
|
||||||
private:
|
static constexpr auto reference = isq::duration[detail::time_unit_from_chrono_period<Period>()];
|
||||||
static constexpr auto mag = ::units::mag<ratio(Period::num, Period::den)>();
|
|
||||||
public:
|
|
||||||
using dimension = isq::si::dim_time;
|
|
||||||
using unit = downcast_unit<dimension, mag>;
|
|
||||||
using rep = Rep;
|
using rep = Rep;
|
||||||
[[nodiscard]] static constexpr rep number(const std::chrono::duration<Rep, Period>& q) { return q.count(); }
|
[[nodiscard]] static constexpr rep number(const std::chrono::duration<Rep, Period>& q) { return q.count(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename C>
|
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>
|
template<typename C, typename Rep, typename Period>
|
||||||
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> {
|
struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::duration<Rep, Period>>> {
|
||||||
private:
|
static constexpr auto reference = isq::time[detail::time_unit_from_chrono_period<Period>()];
|
||||||
static constexpr auto mag = ::units::mag<ratio(Period::num, Period::den)>();
|
static constexpr auto point_origin = chrono_point_origin<C>{};
|
||||||
public:
|
|
||||||
using origin = clock_origin<C>;
|
|
||||||
using unit = downcast_unit<typename origin::dimension, mag>;
|
|
||||||
using rep = Rep;
|
using rep = Rep;
|
||||||
[[nodiscard]] static constexpr auto relative(const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp)
|
[[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<quantity_of<isq::time> Q>
|
||||||
|
[[nodiscard]] constexpr auto to_chrono_duration(const Q& q)
|
||||||
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);
|
constexpr auto canonical = detail::get_canonical_unit(Q::unit);
|
||||||
std::intmax_t res = 1;
|
constexpr ratio r = as_ratio(canonical.mag);
|
||||||
for (std::intmax_t i = 0; i < v; i++) res *= 10;
|
return std::chrono::duration<typename Q::rep, std::ratio<r.num, r.den>>{q.number()};
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<ratio R>
|
template<quantity_point_of<isq::time> QP>
|
||||||
constexpr auto to_std_ratio_impl()
|
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>{};
|
using clock = TYPENAME decltype(QP::absolute_point_origin)::clock;
|
||||||
}
|
using rep = TYPENAME QP::rep;
|
||||||
|
constexpr auto canonical = detail::get_canonical_unit(QP::unit);
|
||||||
} // namespace detail
|
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>>>;
|
||||||
// TODO ICE below on gcc-11 when `ratio` is used instead of `auto`
|
return ret_type(to_std_duration(qp.absolute()));
|
||||||
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()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
Reference in New Issue
Block a user