我有这段代码试图通过添加持续时间来创建新的time_point:
// now
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
// duration
std::chrono::duration<float> duration(1.0f / 60.0f); // float in seconds
// now + duration
std::chrono::system_clock::time_point futureTime = now + duration;
但这给了我这个错误
error: conversion from 'std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<float, std::ratio<1, 1000000000> > >' to non-scalar type 'std::chrono::_V2::system_clock::time_point {aka std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1, 1000000000> > >}' requested
# it's over there in the distance --->
# ... again, with some manual formatting:
error:
conversion from
'std::chrono::time_point<std::chrono::_V2::system_clock,
std::chrono::duration<float,
std::ratio<1, 1000000000> > >'
to non-scalar type
'std::chrono::_V2::system_clock::time_point
{aka
std::chrono::time_point<std::chrono::_V2::system_clock,
std::chrono::duration<long int,
std::ratio<1, 1000000000> > >}'
requested
斜眼看了一些之后,第一个出现了float
,第二个出现了long int
。因此,now (long int) + duration (float)
给出了一个带有内部浮点持续时间的time_point,我想是要求将它填充回默认的long int
表示形式。
我想最终将此时间点传递到std::condition_variable::wait_until
。如何强制转换为std::chrono::system_clock::time_point
?
如果我这样做会丢失哪种精度(即它存储的毫秒数,在这种情况下我会丢失一部分1/60)?
如果我不进行转换,写now + duration
返回的类型的简短方法是什么(是的,我可以使用auto,但是为了将其传递给函数)是
答案 0 :(得分:3)
您对问题所做的分析基本上是正确的。有两种很好的方法可以完成这项工作。 1 , 2
auto
// now
system_clock::time_point now = system_clock::now();
// duration
duration<float> duration(1.0f / 60.0f); // float in seconds
// now + duration
auto futureTime = now + duration;
futureTime
的类型为time_point<system_clock, duration<float, nano>>
。也就是说,它是一个基于time_point
的{{1}},存储着system_clock
表示的nanoseconds
。
此类型可以与float
一起使用。
std::condition_variable::wait_until
放回now + duration
:system_clock::time_point
// now
system_clock::time_point now = system_clock::now();
// duration
duration<float> duration(1.0f / 60.0f); // float in seconds
// now + duration
system_clock::time_point futureTime =
time_point_cast<system_clock::duration>(now + duration);
是投射time_point_cast<duration>
的方式。您必须明确指定希望结果time_point
拥有的持续时间类型。结果time_point
将继续基于同一时钟。
结果将被截断(四舍五入到下一个整数time_point
(在此平台上为system_clock::duration
)。
此类型可以与nanoseconds
一起使用。
std::condition_variable::wait_until
回合到now + duration
:system_clock::time_point
这与之前的解决方案一样,只是将四舍五入到最接近的整数system_clock::time_point futureTime = round<system_clock::duration>(now + duration);
,并平和到平局的nanoseconds
。 nanoseconds
在C ++ 17和更高版本中可用。这将最多带来std::chrono::round
与1ns
不同的结果。
如果您没有C ++ 17,但仍然想使用time_point_cast
,请随时使用this one。
此类型可以与round
一起使用。
std::condition_variable::wait_until
人们常说:
不可能精确地表示 1 / 60 秒。
但是您可以使用// now
system_clock::time_point now = system_clock::now();
// duration
duration<int, std::ratio<1, 60>> duration{1}; // 1/60 of a second
// now + duration
auto futureTime = now + duration;
。 :-) <chrono>
使用duration<int, std::ratio<1, 60>>
的表示形式,以 1 / 60 为单位。 int
是 1 / 60 秒。 duration{1}
是 2 / 60 秒。等等
duration{2}
真的在这里非常有用。 auto
的类型为:futureTime
。或用英语:基于time_point<system_clock, duration<system_clock::rep, ratio<1, 3'000'000'000>>>
的{{1}}使用持续时间,其表示类型为time_point
使用的代表类型(通常为system_clock
),且周期为 1 / 3 system_clock::time_point
。
事实证明, 1 / 3 long long
是最粗的精度,可以精确地 代表nanoseconds
(在此平台上为nanoseconds
)和 1 / 60 秒。
system_clock::period
会自动为您解决所有这些问题。要利用它,您所需要做的就是使用nanoseconds
。
此类型可以与<chrono>
一起使用。
如果您想回到基于纳秒的auto
,还可以将std::condition_variable::wait_until
与duration<int, std::ratio<1, 60>>
或time_point_cast
结合使用,如先前所示。
哪个最好?您将必须根据应用程序中的其他因素来决定。通常,最好的方法是使代码的其余部分更具可读性。
但是您有选择,它们都是不错的选择。他们都将与round
一起工作。
在探索选项时,如果无法编译,那是因为system_clock::time_point
在编译时捕获了错误(就像第一个一样)。如果它可以编译(并且您还没有使用std::condition_variable::wait_until
或<chrono>
转义类型系统),那么它就可以正常工作。
1 该问题的答案假定该问题中报告的.count()
为.time_since_epoch()
。这仅适用于gcc,并且在Windows和macOS上有所不同。
2 为了不至于太冗长,我在写答案时好像有一个:
system_clock::duration
在玩。它使事情如此更具可读性。
答案 1 :(得分:0)
std::condition_variable::wait_until
看起来像这样:(cppreference)
template< class Clock, class Duration >
std::cv_status
wait_until( std::unique_lock<std::mutex>& lock,
const std::chrono::time_point<Clock, Duration>& timeout_time );
template< class Clock, class Duration, class Pred >
bool wait_until( std::unique_lock<std::mutex>& lock,
const std::chrono::time_point<Clock, Duration>& timeout_time,
Pred pred );
您可以将任何time_point<C, D>
传递给它。它不必是system_clock::time_point
。 system_clock::time_point
就是time_point<system_clock>
。
时钟的确切表示方式是实现定义的,但必须为整数类型。 (1/60)s
不能精确地用整数作为数字,以秒为单位表示。
now + duration
,其中now
的类型为time_point<C, D1>
,而duration
的类型为duration<R2, P2>
,类型为time_point<C, std::common_type_t<duration<R1, P1>, D2>>
。