+/*
+ * Helper classes for picking an intermediate duration type to use
+ * when doing conversions to/from durations where neither the numerator nor
+ * denominator are 1.
+ */
+template <typename T, bool IsFloatingPoint, bool IsSigned>
+struct IntermediateTimeRep {};
+template <typename T, bool IsSigned>
+struct IntermediateTimeRep<T, true, IsSigned> {
+ using type = T;
+};
+template <typename T>
+struct IntermediateTimeRep<T, false, true> {
+ using type = intmax_t;
+};
+template <typename T>
+struct IntermediateTimeRep<T, false, false> {
+ using type = uintmax_t;
+};
+// For IntermediateDuration we always use 1 as the numerator, and the original
+// Period denominator. This ensures that we do not lose precision when
+// performing the conversion.
+template <typename Rep, typename Period>
+using IntermediateDuration = std::chrono::duration<
+ typename IntermediateTimeRep<
+ Rep,
+ std::is_floating_point<Rep>::value,
+ std::is_signed<Rep>::value>::type,
+ std::ratio<1, Period::den>>;
+