diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 13aa077e..2982bbea 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -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 diff --git a/docs/use_cases/interoperability.rst b/docs/use_cases/interoperability.rst index 1fd7685c..ca967d30 100644 --- a/docs/use_cases/interoperability.rst +++ b/docs/use_cases/interoperability.rst @@ -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 + +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 Q> + constexpr auto to_std_duration(const Q& q); + +- an alias that provides a conversion from `ratio` to ``std::ratio``:: + + template + using to_std_ratio = /* ... */ diff --git a/src/core/include/units/chrono.h b/src/core/include/units/chrono.h index d85496bd..8e040de2 100644 --- a/src/core/include/units/chrono.h +++ b/src/core/include/units/chrono.h @@ -58,6 +58,36 @@ namespace detail { template inline constexpr bool is_quantity_point_like>> = 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 +constexpr auto to_std_ratio_impl() +{ + if constexpr(R.exp == 0) + return std::ratio{}; + else if constexpr(R.exp > 0) + return std::ratio{}; + else + 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 Q> +constexpr auto to_std_duration(const Q& q) +{ + return std::chrono::duration>(q.number()); +} + } // namespace units diff --git a/test/unit_test/static/chrono_test.cpp b/test/unit_test/static/chrono_test.cpp index ed812548..d5592de2 100644 --- a/test/unit_test/static/chrono_test.cpp +++ b/test/unit_test/static/chrono_test.cpp @@ -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{2_q_s}); static_assert(quantity_point{sys_seconds{1s}} + 1_q_min == time_point{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>); +static_assert(is_same_v>); +static_assert(is_same_v); + } // namespace