c++ - 错误:请求从 std::chrono::time_point float 到非标量类型 long int 的转换

标签 c++ c++11 c++-chrono

我有这段代码试图通过添加持续时间来创建一个新的 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 , 存储 nanosecondsfloat 代表.

此类型可与 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_castround如前所示,如果您想回到基于纳秒的 system_clock::time_point .

总结

哪个最好?您必须根据申请中的其他因素来决定。通常最好的是让其余代码更具可读性。

但是您有多种选择,而且都是不错的选择。他们都将与 std::condition_variable::wait_until 一起工作.

当你探索你的选择时,如果它没有编译,那是因为 <chrono>在编译时捕获你的错误(就像第一个一样)。如果它编译(并且如果你没有使用 .count().time_since_epoch() 转义类型系统),那么它就可以工作。


1 这个问题的答案假设system_clock::durationnanoseconds如问题中所述。这仅适用于 gcc,并且在 Windows 和 macOS 上有所不同。

2 为了不被冗长所迷惑,我正在写我的答案,就好像有一个:

using namespace std::chrono;

在玩。它使事情如此更具可读性。

关于c++ - 错误:请求从 std::chrono::time_point float 到非标量类型 long int 的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56679067/

相关文章:

c++ - Push_back({ "George", 1 }) 和 Push_back(Student ("Jack", 10)); 有什么区别

c++ - 为什么 std::chrono 在测量 OpenMP 并行化 for 循环和编译器优化的执行时间时不起作用?

c++ - 如何在 SDL 2.0 中绘制像素?

C++0x 右值引用 - 左值-右值绑定(bind)

c++ - Qt 5.1 - QMessageBox 错误?如果在隐藏 QDialog 时调用 QMessageBox,则程序退出(0)

c++ - C++ 中的指针和多维数组

c++ - std::chrono::duration::max() 不适用于线程支持库

c++ - 将两个 chrono::durations 除以得到分数

c++ - 复制构造函数后链表中的访问冲突

c++ - 为什么在 Qt 源代码文件末尾包含 ".moc"文件很重要?