QDateTime::fromStdTimePoint: fix the constraint

The constraint requires the input time_point's duration to be
convertible to milliseconds. That's inaccurate: we need to check the
duration of the time_point we get from the clock_cast, not the input.
In general, clock_cast is allowed to return arbitrary durations, so
it may not match the input. (It indeed doesn't match for some
standard clocks, like gps_clock.)

Task-number: QTBUG-125587
Change-Id: I5a93317c8cdc0a3cef4acab17c656e2e5dac5d8d
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit e95812df85d98689d51bed92acce51e0e250f854)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Giuseppe D'Angelo 2024-05-23 19:58:19 +02:00 committed by Qt Cherry-pick Bot
parent 7f219f23b4
commit 6197078fbd
2 changed files with 28 additions and 4 deletions

View File

@ -5352,8 +5352,17 @@ QDateTime QDateTime::currentDateTimeUtc()
Constructs a datetime representing the same point in time as \a time,
using Qt::UTC as its specification.
The clock of \a time must be compatible with \c{std::chrono::system_clock},
and the duration type must be convertible to \c{std::chrono::milliseconds}.
The clock of \a time must be compatible with
\c{std::chrono::system_clock}; in particular, a conversion
supported by \c{std::chrono::clock_cast} must exist. After the
conversion, the duration type of the result must be convertible to
\c{std::chrono::milliseconds}.
If this is not the case, the caller must perform the necessary
clock conversion towards \c{std::chrono::system_clock} and the
necessary conversion of the duration type
(cast/round/floor/ceil/...) so that the input to this function
satisfies the constraints above.
\note This function requires C++20.

View File

@ -510,6 +510,17 @@ public:
#if __cpp_lib_chrono >= 201907L || defined(Q_QDOC)
#if __cpp_concepts >= 201907L || defined(Q_QDOC)
private:
// The duration type of the result of a clock_cast<system_clock>.
// This duration may differ from the duration of the input.
template <typename Clock, typename Duration>
using system_clock_cast_duration = decltype(
std::chrono::clock_cast<std::chrono::system_clock>(
std::declval<const std::chrono::time_point<Clock, Duration> &>()
).time_since_epoch()
);
public:
// Generic clock, as long as it's compatible with us (= system_clock)
template <typename Clock, typename Duration>
static QDateTime fromStdTimePoint(const std::chrono::time_point<Clock, Duration> &time)
@ -517,8 +528,12 @@ public:
requires(const std::chrono::time_point<Clock, Duration> &t) {
// the clock can be converted to system_clock
std::chrono::clock_cast<std::chrono::system_clock>(t);
// the duration can be converted to milliseconds
requires std::is_convertible_v<Duration, std::chrono::milliseconds>;
// after the conversion to system_clock, the duration type
// we get is convertible to milliseconds
requires std::is_convertible_v<
system_clock_cast_duration<Clock, Duration>,
std::chrono::milliseconds
>;
}
{
const auto sysTime = std::chrono::clock_cast<std::chrono::system_clock>(time);