diff --git a/src/core/include/units/chrono.h b/src/core/include/units/chrono.h index d7b900a1..7a09e956 100644 --- a/src/core/include/units/chrono.h +++ b/src/core/include/units/chrono.h @@ -23,35 +23,56 @@ #pragma once #include -// IWYU pragma: begin_exports -#include -#include +#include +#include +#include #include -// IWYU pragma: end_exports namespace units { +namespace detail { + +template +[[nodiscard]] inline consteval auto time_unit_from_chrono_period() +{ + using namespace si; + + if constexpr (is_same_v) + return nano; + else if constexpr (is_same_v) + return micro; + else if constexpr (is_same_v) + return milli; + else if constexpr (is_same_v) + return second; + else if constexpr (is_same_v) + return minute; + else if constexpr (is_same_v) + return hour; + else if constexpr (is_same_v) + return day; + else + return mag * second; +} + +} // namespace detail + template struct quantity_like_traits> { -private: - static constexpr auto mag = ::units::mag(); -public: - using dimension = isq::si::dim_time; - using unit = downcast_unit; + static constexpr auto reference = isq::duration[detail::time_unit_from_chrono_period()]; using rep = Rep; [[nodiscard]] static constexpr rep number(const std::chrono::duration& q) { return q.count(); } }; template -struct clock_origin : point_origin {}; +struct chrono_point_origin : absolute_point_origin { + using clock = C; +}; template struct quantity_point_like_traits>> { -private: - static constexpr auto mag = ::units::mag(); -public: - using origin = clock_origin; - using unit = downcast_unit; + static constexpr auto reference = isq::time[detail::time_unit_from_chrono_period()]; + static constexpr auto point_origin = chrono_point_origin{}; using rep = Rep; [[nodiscard]] static constexpr auto relative(const std::chrono::time_point>& qp) { @@ -59,42 +80,24 @@ public: } }; -namespace detail { - -template -inline constexpr bool is_quantity_point_like>> = true; - -constexpr std::intmax_t pow_10(std::intmax_t v) +template 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>{q.number()}; } -template -constexpr auto to_std_ratio_impl() +template QP> + requires is_specialization_of, chrono_point_origin> +[[nodiscard]] constexpr auto to_chrono_time_point(const QP& qp) { - return std::ratio{}; -} - -} // namespace detail - -// TODO ICE below on gcc-11 when `ratio` is used instead of `auto` -template -using to_std_ratio = decltype(detail::to_std_ratio_impl()); - -template -[[nodiscard]] constexpr auto to_std_duration(const quantity& q) -{ - return std::chrono::duration>(q.number()); -} - -template -[[nodiscard]] constexpr auto to_std_time_point(const quantity_point, U, Rep>& qp) -{ - using ret_type = std::chrono::time_point>>; - 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>>; + return ret_type(to_std_duration(qp.absolute())); } } // namespace units