Commit 3c9a6e9a authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

No need for a wrapping structure for posixTimeToDuration

Summary:
[Folly] No need for a wrapping structure for `posixTimeToDuration`.

We can just use a variant of tag dispatch. In this variant, we pass to `posixTimeToDuration` a default-initialized value of the desired return type and we write overload templates for each possible variant. The argument is used purely for overload resolution and return type deduction, not for its runtime value. It is slightly different from tag dispatch because we do not use separate types which are purely tag types.

Reviewed By: simpkins

Differential Revision: D6371572

fbshipit-source-id: 1987dee31fceec8733caa61495e96489dbf1ca39
parent 7046d43c
...@@ -323,8 +323,8 @@ struct CheckOverflowToDuration<true> { ...@@ -323,8 +323,8 @@ struct CheckOverflowToDuration<true> {
}; };
/** /**
* Helper class to convert a POSIX-style pair of (seconds, subseconds) * Convert a timeval or a timespec to a std::chrono::duration with second
* to a std::chrono::duration type. * granularity.
* *
* The SubsecondRatio template parameter specifies what type of subseconds to * The SubsecondRatio template parameter specifies what type of subseconds to
* return. This must have a numerator of 1. * return. This must have a numerator of 1.
...@@ -332,30 +332,18 @@ struct CheckOverflowToDuration<true> { ...@@ -332,30 +332,18 @@ struct CheckOverflowToDuration<true> {
* The input must be in normalized form: the subseconds field must be greater * The input must be in normalized form: the subseconds field must be greater
* than or equal to 0, and less than SubsecondRatio::den (i.e., less than 1 * than or equal to 0, and less than SubsecondRatio::den (i.e., less than 1
* second). * second).
*
* This default implementation is only used for unusual std::chrono::duration
* types where neither the numerator nor denominator are 1.
*/
template <typename Tgt>
struct PosixTimeToDuration {
template <typename SubsecondRatio, typename Seconds, typename Subseconds>
static Expected<Tgt, ConversionCode> cast(
Seconds seconds,
Subseconds subseconds);
};
/**
* Convert a timeval or a timespec to a std::chrono::duration with second
* granularity.
*/ */
template <typename Rep> template <
struct PosixTimeToDuration<std::chrono::duration<Rep, std::ratio<1, 1>>> { typename SubsecondRatio,
using Tgt = std::chrono::duration<Rep, std::ratio<1, 1>>; typename Seconds,
typename Subseconds,
template <typename SubsecondRatio, typename Seconds, typename Subseconds> typename Rep>
static Expected<Tgt, ConversionCode> cast( auto posixTimeToDuration(
Seconds seconds, Seconds seconds,
Subseconds subseconds) { Subseconds subseconds,
std::chrono::duration<Rep, std::ratio<1, 1>> dummy)
-> Expected<decltype(dummy), ConversionCode> {
using Tgt = decltype(dummy);
static_assert(Tgt::period::num == 1, "special case expecting num==1"); static_assert(Tgt::period::num == 1, "special case expecting num==1");
static_assert(Tgt::period::den == 1, "special case expecting den==1"); static_assert(Tgt::period::den == 1, "special case expecting den==1");
static_assert( static_assert(
...@@ -382,22 +370,24 @@ struct PosixTimeToDuration<std::chrono::duration<Rep, std::ratio<1, 1>>> { ...@@ -382,22 +370,24 @@ struct PosixTimeToDuration<std::chrono::duration<Rep, std::ratio<1, 1>>> {
} }
return Tgt{outputSeconds.value()}; return Tgt{outputSeconds.value()};
} }
};
/** /**
* Convert a timeval or a timespec to a std::chrono::duration with subsecond * Convert a timeval or a timespec to a std::chrono::duration with subsecond
* granularity * granularity
*/ */
template <typename Rep, std::intmax_t Denominator> template <
struct PosixTimeToDuration< typename SubsecondRatio,
std::chrono::duration<Rep, std::ratio<1, Denominator>>> { typename Seconds,
using Tgt = std::chrono::duration<Rep, std::ratio<1, Denominator>>; typename Subseconds,
typename Rep,
template <typename SubsecondRatio, typename Seconds, typename Subseconds> std::intmax_t Denominator>
static Expected<Tgt, ConversionCode> cast( auto posixTimeToDuration(
Seconds seconds, Seconds seconds,
Subseconds subseconds) { Subseconds subseconds,
std::chrono::duration<Rep, std::ratio<1, Denominator>> dummy)
-> Expected<decltype(dummy), ConversionCode> {
using Tgt = decltype(dummy);
static_assert(Tgt::period::num == 1, "special case expecting num==1"); static_assert(Tgt::period::num == 1, "special case expecting num==1");
static_assert(Tgt::period::den != 1, "special case expecting den!=1"); static_assert(Tgt::period::den != 1, "special case expecting den!=1");
static_assert( static_assert(
...@@ -425,22 +415,24 @@ struct PosixTimeToDuration< ...@@ -425,22 +415,24 @@ struct PosixTimeToDuration<
std::chrono::duration<typename Tgt::rep, SubsecondRatio>{ std::chrono::duration<typename Tgt::rep, SubsecondRatio>{
SubsecondRatio::den - subseconds}); SubsecondRatio::den - subseconds});
} }
} }
};
/** /**
* Convert a timeval or a timespec to a std::chrono::duration with * Convert a timeval or a timespec to a std::chrono::duration with
* granularity coarser than 1 second. * granularity coarser than 1 second.
*/ */
template <typename Rep, std::intmax_t Numerator> template <
struct PosixTimeToDuration< typename SubsecondRatio,
std::chrono::duration<Rep, std::ratio<Numerator, 1>>> { typename Seconds,
using Tgt = std::chrono::duration<Rep, std::ratio<Numerator, 1>>; typename Subseconds,
typename Rep,
template <typename SubsecondRatio, typename Seconds, typename Subseconds> std::intmax_t Numerator>
static Expected<Tgt, ConversionCode> cast( auto posixTimeToDuration(
Seconds seconds, Seconds seconds,
Subseconds subseconds) { Subseconds subseconds,
std::chrono::duration<Rep, std::ratio<Numerator, 1>> dummy)
-> Expected<decltype(dummy), ConversionCode> {
using Tgt = decltype(dummy);
static_assert(Tgt::period::num != 1, "special case expecting num!=1"); static_assert(Tgt::period::num != 1, "special case expecting num!=1");
static_assert(Tgt::period::den == 1, "special case expecting den==1"); static_assert(Tgt::period::den == 1, "special case expecting den==1");
static_assert( static_assert(
...@@ -469,18 +461,27 @@ struct PosixTimeToDuration< ...@@ -469,18 +461,27 @@ struct PosixTimeToDuration<
return Tgt{expectedOuput.value()}; return Tgt{expectedOuput.value()};
} }
} }
};
/** /**
* PosixTimeToDuration::cast() implementation for the default case * Convert a timeval or timespec to a std::chrono::duration
* with unusual durations where neither the numerator nor denominator are 1. *
* This overload is only used for unusual durations where neither the numerator
* nor denominator are 1.
*/ */
template <typename Tgt> template <
template <typename SubsecondRatio, typename Seconds, typename Subseconds> typename SubsecondRatio,
Expected<Tgt, ConversionCode> PosixTimeToDuration<Tgt>::cast( typename Seconds,
typename Subseconds,
typename Rep,
std::intmax_t Denominator,
std::intmax_t Numerator>
auto posixTimeToDuration(
Seconds seconds, Seconds seconds,
Subseconds subseconds) { Subseconds subseconds,
std::chrono::duration<Rep, std::ratio<Numerator, Denominator>> dummy)
-> Expected<decltype(dummy), ConversionCode> {
using Tgt = decltype(dummy);
static_assert( static_assert(
Tgt::period::num != 1, "should use special-case code when num==1"); Tgt::period::num != 1, "should use special-case code when num==1");
static_assert( static_assert(
...@@ -534,8 +535,7 @@ Expected<Tgt, ConversionCode> tryPosixTimeToDuration( ...@@ -534,8 +535,7 @@ Expected<Tgt, ConversionCode> tryPosixTimeToDuration(
subseconds = remainder; subseconds = remainder;
} }
using Converter = PosixTimeToDuration<Tgt>; return posixTimeToDuration<SubsecondRatio>(seconds, subseconds, Tgt{});
return Converter::template cast<SubsecondRatio>(seconds, subseconds);
} }
} // namespace detail } // namespace detail
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment