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> {
};
/**
* Helper class to convert a POSIX-style pair of (seconds, subseconds)
* to a std::chrono::duration type.
* Convert a timeval or a timespec to a std::chrono::duration with second
* granularity.
*
* The SubsecondRatio template parameter specifies what type of subseconds to
* return. This must have a numerator of 1.
......@@ -332,30 +332,18 @@ struct CheckOverflowToDuration<true> {
* 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
* 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>
struct PosixTimeToDuration<std::chrono::duration<Rep, std::ratio<1, 1>>> {
using Tgt = std::chrono::duration<Rep, std::ratio<1, 1>>;
template <typename SubsecondRatio, typename Seconds, typename Subseconds>
static Expected<Tgt, ConversionCode> cast(
template <
typename SubsecondRatio,
typename Seconds,
typename Subseconds,
typename Rep>
auto posixTimeToDuration(
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::den == 1, "special case expecting den==1");
static_assert(
......@@ -382,22 +370,24 @@ struct PosixTimeToDuration<std::chrono::duration<Rep, std::ratio<1, 1>>> {
}
return Tgt{outputSeconds.value()};
}
};
}
/**
* Convert a timeval or a timespec to a std::chrono::duration with subsecond
* granularity
*/
template <typename Rep, std::intmax_t Denominator>
struct PosixTimeToDuration<
std::chrono::duration<Rep, std::ratio<1, Denominator>>> {
using Tgt = std::chrono::duration<Rep, std::ratio<1, Denominator>>;
template <typename SubsecondRatio, typename Seconds, typename Subseconds>
static Expected<Tgt, ConversionCode> cast(
template <
typename SubsecondRatio,
typename Seconds,
typename Subseconds,
typename Rep,
std::intmax_t Denominator>
auto posixTimeToDuration(
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::den != 1, "special case expecting den!=1");
static_assert(
......@@ -425,22 +415,24 @@ struct PosixTimeToDuration<
std::chrono::duration<typename Tgt::rep, SubsecondRatio>{
SubsecondRatio::den - subseconds});
}
}
};
}
/**
* Convert a timeval or a timespec to a std::chrono::duration with
* granularity coarser than 1 second.
*/
template <typename Rep, std::intmax_t Numerator>
struct PosixTimeToDuration<
std::chrono::duration<Rep, std::ratio<Numerator, 1>>> {
using Tgt = std::chrono::duration<Rep, std::ratio<Numerator, 1>>;
template <typename SubsecondRatio, typename Seconds, typename Subseconds>
static Expected<Tgt, ConversionCode> cast(
template <
typename SubsecondRatio,
typename Seconds,
typename Subseconds,
typename Rep,
std::intmax_t Numerator>
auto posixTimeToDuration(
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::den == 1, "special case expecting den==1");
static_assert(
......@@ -469,18 +461,27 @@ struct PosixTimeToDuration<
return Tgt{expectedOuput.value()};
}
}
};
}
/**
* PosixTimeToDuration::cast() implementation for the default case
* with unusual durations where neither the numerator nor denominator are 1.
* Convert a timeval or timespec to a std::chrono::duration
*
* This overload is only used for unusual durations where neither the numerator
* nor denominator are 1.
*/
template <typename Tgt>
template <typename SubsecondRatio, typename Seconds, typename Subseconds>
Expected<Tgt, ConversionCode> PosixTimeToDuration<Tgt>::cast(
template <
typename SubsecondRatio,
typename Seconds,
typename Subseconds,
typename Rep,
std::intmax_t Denominator,
std::intmax_t Numerator>
auto posixTimeToDuration(
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(
Tgt::period::num != 1, "should use special-case code when num==1");
static_assert(
......@@ -534,8 +535,7 @@ Expected<Tgt, ConversionCode> tryPosixTimeToDuration(
subseconds = remainder;
}
using Converter = PosixTimeToDuration<Tgt>;
return Converter::template cast<SubsecondRatio>(seconds, subseconds);
return posixTimeToDuration<SubsecondRatio>(seconds, subseconds, Tgt{});
}
} // 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