<chrono>Previous revision: P0092R0
time_point.
floor Returns:.
ceil Returns:.
round Returns:.
round Returns:.
abs Remarks:.
This paper proposes a few minor additions to the chrono library to make it easier to use and more uniform:
Alternative rounding modes for durations and time_points:
floor: round towards negative infinity.ceil: round towards positive infinity.round: : round towards nearest, to even on tie.
abs only for signed duration types.
These are minor additions that make chrono easier to use. They have been implemented and used for years. They should have been part of the original chrono proposal for C++11, but simply slipped through the cracks by no one's fault but my own.
The rounding modes differ from duration_cast and time_point_cast
in that these existing rounding functions truncate towards zero: downwards for postive
values and upwards for negative values.
The implementation is shown below for the utility functions. This presentation is meant to:
Fully inform the intent of this proposal.
Immediately convey the scope and the small-ness of this proposal.
Show the ease of implementation of this proposal.
This implementation is consistent with that which has been up on my personal website for years.
namespace std { namespace chrono {
namespace detail
{
template <class T>
struct is_duration
: public false_type
{};
template <class Rep, class Period>
struct is_duration<duration<Rep, Period>>
: public true_type
{};
} // namespace detail
template <class To, class Rep, class Period,
class = enable_if_t<detail::is_duration<To>{}>>
constexpr
To
floor(const duration<Rep, Period>& d)
{
To t = duration_cast<To>(d);
if (t > d)
--t;
return t;
}
template <class To, class Rep, class Period,
class = enable_if_t<detail::is_duration<To>{}>>
constexpr
To
ceil(const duration<Rep, Period>& d)
{
To t = duration_cast<To>(d);
if (t < d)
++t;
return t;
}
template <class To, class Rep, class Period,
class = enable_if_t<detail::is_duration<To>{}
&& !treat_as_floating_point<typename To::rep>{}>>
constexpr
To
round(const duration<Rep, Period>& d)
{
To t0 = floor<To>(d);
To t1 = t0 + To{1};
auto diff0 = d - t0;
auto diff1 = t1 - d;
if (diff0 == diff1)
{
if (t0.count() & 1)
return t1;
return t0;
}
else if (diff0 < diff1)
return t0;
return t1;
}
template <class To, class Clock, class FromDuration,
class = enable_if_t<detail::is_duration<To>{}>>
constexpr
time_point<Clock, To>
floor(const time_point<Clock, FromDuration>& tp)
{
return time_point<Clock, To>{floor<To>(tp.time_since_epoch())};
}
template <class To, class Clock, class FromDuration,
class = enable_if_t<detail::is_duration<To>{}>>
constexpr
time_point<Clock, To>
ceil(const time_point<Clock, FromDuration>& tp)
{
return time_point<Clock, To>{ceil<To>(tp.time_since_epoch())};
}
template <class To, class Clock, class FromDuration,
class = enable_if_t<detail::is_duration<To>{}
&& !treat_as_floating_point<typename To::rep>{}>>
constexpr
time_point<Clock, To>
round(const time_point<Clock, FromDuration>& tp)
{
return time_point<Clock, To>{round<To>(tp.time_since_epoch())};
}
template <class Rep, class Period,
class = enable_if_t
<
duration<Rep, Period>::min() < duration<Rep, Period>::zero()
> >
constexpr
duration<Rep, Period>
abs(duration<Rep, Period> d)
{
return d >= d.zero() ? d : -d;
}
} } // namespace std::chrono
Add to 20.12.2 Header <chrono> synopsis [time.syn], under
duration_cast:
template <class ToDuration, class Rep, class Period>
constexpr ToDuration floor(const duration<Rep, Period>& d);
template <class ToDuration, class Rep, class Period>
constexpr ToDuration ceil(const duration<Rep, Period>& d);
template <class ToDuration, class Rep, class Period>
constexpr ToDuration round(const duration<Rep, Period>& d);
Add to 20.12.2 Header <chrono> synopsis [time.syn], under
time_point_cast:
template <class ToDuration, class Clock, class Duration>
constexpr time_point<Clock, ToDuration>
floor(const time_point<Clock, Duration>& tp);
template <class ToDuration, class Clock, class Duration>
constexpr time_point<Clock, ToDuration>
ceil(const time_point<Clock, Duration>& tp);
template <class ToDuration, class Clock, class Duration>
constexpr time_point<Clock, ToDuration>
round(const time_point<Clock, Duration>& tp);
Add a new section to 20.12.2 Header <chrono> synopsis [time.syn]
(specialized algorithms: — within namespace std::chrono):
template <class Rep, class Period>
constexpr duration<Rep, Period> abs(duration<Rep, Period> d)
Add to 20.12.5.7 <duration_cast> [time.duration.cast]:
template <class ToDuration, class Rep, class Period> constexpr ToDuration floor(const duration<Rep, Period>& d);Remarks: This function shall not participate in overload resolution unless
ToDurationis a specialization ofduration.Returns: The greatest result
trepresentable inToDurationfor whicht <= d.template <class ToDuration, class Rep, class Period> constexpr ToDuration ceil(const duration<Rep, Period>& d);Remarks: This function shall not participate in overload resolution unless
ToDurationis a specialization ofduration.Returns: The least result
trepresentable inToDurationfor whicht >= d.template <class ToDuration, class Rep, class Period> constexpr ToDuration round(const duration<Rep, Period>& d);Remarks: This function shall not participate in overload resolution unless
ToDurationis a specialization ofduration, andtreat_as_floating_point<typename ToDuration::rep>::valueisfalse.Returns: The value of
ToDurationthat is closest tod. If there are two closest values, then return the valuetfor whicht % 2 == 0.
Add a new section to 20.12.5 [time.duration]: duration algorithms [time.duration.alg].
template <class Rep, class Period> constexpr duration<Rep, Period> abs(duration<Rep, Period> d)Remarks: This function shall not participate in overload resolution unless
numeric_limits<Rep>::is_signedistrue.Returns: If
d >= d.zero(), returnd, otherwise return-d.
Add to 20.12.6.7 time_point_cast [time.point.cast]:
template <class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> floor(const time_point<Clock, Duration>& tp);Remarks: This function shall not participate in overload resolution unless
ToDurationis a specialization ofduration.Returns:
time_point<Clock, ToDuration>{floor<ToDuration>(tp.time_since_epoch())}.template <class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> ceil(const time_point<Clock, Duration>& tp);Remarks: This function shall not participate in overload resolution unless
ToDurationis a specialization ofduration.Returns:
time_point<Clock, ToDuration>{ceil<ToDuration>(tp.time_since_epoch())}.template <class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> round(const time_point<Clock, Duration>& tp);Remarks: This function shall not participate in overload resolution unless
ToDurationis a specialization ofduration, andtreat_as_floating_point<typename ToDuration::rep>::valueisfalse.Returns:
time_point<Clock, ToDuration>{round<ToDuration>(tp.time_since_epoch())}.
Modify 20.12.5.5 duration non-member arithmetic [time.duration.nonmember]:
template <class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator/(const duration<Rep1, Period>& d, const Rep2& s);Remarks: This operator shall not participate in overload resolution unless
Rep2is implicitly convertible toCR(Rep1, Rep2)andRep2is notan instantiationa specialization ofduration....
template <class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator%(const duration<Rep1, Period>& d, const Rep2& s);Remarks: This operator shall not participate in overload resolution unless
Rep2is implicitly convertible toCR(Rep1, Rep2)andRep2is notan instantiationa specialization ofduration.
Modify 20.12.5.7 duration_cast [time.duration.cast]:
template <class ToDuration, class Rep, class Period> constexpr ToDuration duration_cast(const duration<Rep, Period>& d);Remarks: This operator shall not participate in overload resolution unless
ToDurationisan instantiationa specialization ofduration.
Modify 20.12.6.7 time_point_cast [time.point.cast]:
template <class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration>& t);Remarks: This operator shall not participate in overload resolution unless
ToDurationisan instantiationa specialization ofduration.