我有这段代码试图通过添加持续时间来创建一个新的 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 但为了将它传递给函数) ?
最佳答案
你在问题中所做的分析基本正确。有几种好方法可以让这项工作成功。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
基于 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
在一条领带上。 std::chrono::round
在 C++17 及更高版本中可用。这将最多给出一个结果 1ns
不同于 time_point_cast
.
如果您没有 C++17 但仍想使用 round
, 欢迎使用 this one .
此类型可与 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;
人们常说:
It isn't possible to represent 1/60 second precisely.
但是你可以用 <chrono>
. :-) duration<int, std::ratio<1, 60>>
使用 int
的表示以 1/60 为单位计数. duration{1}
是 1/60 秒。 duration{2}
是 2/60 秒。等等
auto
真的在这里派上用场。 futureTime
的类型是:time_point<system_clock, duration<system_clock::rep, ratio<1, 3'000'000'000>>>
.或英文:A time_point
基于 system_clock
使用任何表示类型的持续时间 system_clock::time_point
使用(通常为 long long
)和 1/3 nanoseconds
的周期.
结果是1/3 nanoseconds
是能够准确同时表示 system_clock::period
的最粗略精度(在此平台上为 nanoseconds
)和 1/60 秒。
和<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>
在编译时捕获你的错误(就像第一个一样)。如果它编译(并且如果你没有使用 .count()
或 .time_since_epoch()
转义类型系统),那么它就可以工作。
1 这个问题的答案假设system_clock::duration
是nanoseconds
如问题中所述。这仅适用于 gcc,并且在 Windows 和 macOS 上有所不同。
2 为了不被冗长所迷惑,我正在写我的答案,就好像有一个:
using namespace std::chrono;
在玩。它使事情如此更具可读性。
关于c++ - 错误:请求从 std::chrono::time_point float 到非标量类型 long int 的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56679067/