From 215cacff5621cbe6a88e24540f3fb7968c7e3b79 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Sun, 25 Oct 2020 20:16:07 -0400 Subject: [PATCH] Change all uses of round to detail::round_i Fixes #613 detail::round_i is the same as round when the To::rep is integral, and is just an implicit conversion when To::rep is floating point. --- include/date/date.h | 58 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/include/date/date.h b/include/date/date.h index e70cac4..bf5fe02 100644 --- a/include/date/date.h +++ b/include/date/date.h @@ -1358,6 +1358,47 @@ using std::chrono::abs; #endif // HAS_CHRONO_ROUNDING +namespace detail +{ + +template +CONSTCD14 +inline +typename std::enable_if +< + !std::chrono::treat_as_floating_point::value, + To +>::type +round_i(const std::chrono::duration& d) +{ + return round(d); +} + +template +CONSTCD14 +inline +typename std::enable_if +< + std::chrono::treat_as_floating_point::value, + To +>::type +round_i(const std::chrono::duration& d) +{ + return d; +} + +template +CONSTCD11 +inline +std::chrono::time_point +round_i(const std::chrono::time_point& tp) +{ + using std::chrono::time_point; + return time_point{round_i(tp.time_since_epoch())}; +} + +} // detail + // trunc towards zero template CONSTCD11 @@ -6315,6 +6356,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, using std::chrono::seconds; using std::chrono::minutes; using std::chrono::hours; + using detail::round_i; typename std::basic_istream::sentry ok{is, true}; if (ok) { @@ -6528,7 +6570,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, CharT{':'}, rld{S, 1, w}); checked_set(H, tH, not_a_hour, is); checked_set(M, tM, not_a_minute, is); - checked_set(s, round(duration{S}), + checked_set(s, round_i(duration{S}), not_a_second, is); ws(is); int tY = not_a_year; @@ -6608,7 +6650,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, CharT{':'}, rld{S, 1, w}); checked_set(H, tH, not_a_hour, is); checked_set(M, tM, not_a_minute, is); - checked_set(s, round(duration{S}), + checked_set(s, round_i(duration{S}), not_a_second, is); #endif } @@ -6965,7 +7007,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, CharT{':'}, rld{S, 1, w}); checked_set(I, tI, not_a_hour_12_value, is); checked_set(M, tM, not_a_minute, is); - checked_set(s, round(duration{S}), + checked_set(s, round_i(duration{S}), not_a_second, is); ws(is); auto nm = detail::ampm_names(); @@ -7016,7 +7058,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; long double S; read(is, rld{S, 1, width == -1 ? w : static_cast(width)}); - checked_set(s, round(duration{S}), + checked_set(s, round_i(duration{S}), not_a_second, is); } #if !ONLY_C_LOCALE @@ -7053,7 +7095,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, CharT{':'}, rld{S, 1, w}); checked_set(H, tH, not_a_hour, is); checked_set(M, tM, not_a_minute, is); - checked_set(s, round(duration{S}), + checked_set(s, round_i(duration{S}), not_a_second, is); } else @@ -7756,6 +7798,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, std::chrono::minutes* offset = nullptr) { using CT = typename std::common_type::type; + using detail::round_i; std::chrono::minutes offset_local{}; auto offptr = offset ? offset : &offset_local; fields fds{}; @@ -7764,7 +7807,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) is.setstate(std::ios::failbit); if (!is.fail()) - tp = round(sys_days(fds.ymd) - *offptr + fds.tod.to_duration()); + tp = round_i(sys_days(fds.ymd) - *offptr + fds.tod.to_duration()); return is; } @@ -7775,13 +7818,14 @@ from_stream(std::basic_istream& is, const CharT* fmt, std::chrono::minutes* offset = nullptr) { using CT = typename std::common_type::type; + using detail::round_i; fields fds{}; fds.has_tod = true; from_stream(is, fmt, fds, abbrev, offset); if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) is.setstate(std::ios::failbit); if (!is.fail()) - tp = round(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration()); + tp = round_i(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration()); return is; }