错误:请求从 std::chrono::time_point 浮点数转换为非标量类型长整型

error: conversion from std::chrono::time_point float to non-scalar type long int requested

本文关键字:转换 类型 长整型 浮点数 标量 请求 std chrono 错误 time point      更新时间:2023-10-16

我有这段代码,它试图通过添加持续时间来创建新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,但为了说将其传递给函数)?

你在问题中所做的分析基本上是正确的。 有几个好方法可以做到这一点。12

使用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>>。 也就是说,它是一个基于system_clocktime_point,存储由float表示的nanoseconds

此类型可以与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,以及平局上的偶数nanosecondsstd::chrono::round在 C++17 及更高版本中可用。 这将给出最多1nstime_point_cast不同的结果。

如果您没有 C++17 但仍想使用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;

人们常说:

不可能精确地表示1/60秒。

但是你可以用<chrono>:-)duration<int, std::ratio<1, 60>>1/60秒为单位计数,使用int表示形式。duration{1}1/60秒。duration{2}2/60秒。 等。

auto在这里真的派上用场了。futureTime的类型是:time_point<system_clock, duration<system_clock::rep, ratio<1, 3'000'000'000>>>。 或英语:基于system_clocktime_point,使用持续时间,表示类型为system_clock::time_point使用的任何内容(通常为long long),周期为1/3nanoseconds

事实证明,1/3nanoseconds是最的精度,可以准确地表示system_clock::period(nanoseconds在这个平台上)和1/60秒。

<chrono>会自动为您解决所有这些问题。 要利用它,您所要做的就是使用auto.

此类型可以与std::condition_variable::wait_until一起使用。

如果您想回到基于纳秒的system_clock::time_point,还可以将duration<int, std::ratio<1, 60>>time_point_castround结合使用,如前所述。

总结

哪个最好? 您必须根据应用程序中的其他因素来决定。 通常,最好的是使其余代码更具可读性。

但是你有选择,它们都是不错的选择。 他们都将与std::condition_variable::wait_until一起工作.

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


1本问题的答案假定system_clock::duration与问题中报告nanoseconds。 这仅适用于gcc,在Windows和macOS上有所不同。

2为了不迷失在冗长中,我写我的答案好像有一个:

using namespace std::chrono;

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

std::condition_variable::wait_until看起来像这样:(cpp首选项)

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,其中nowtime_point<C, D1>型,durationduration<R2, P2>型,是time_point<C, std::common_type_t<duration<R1, P1>, D2>>型。