错误:从std :: chrono :: time_point浮点型到非标量类型long int的转换

时间:2019-06-20 04:36:40

标签: c++ c++11 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,但是为了将其传递给函数)是

2 个答案:

答案 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); ,并平和到平局的nanosecondsnanoseconds在C ++ 17和更高版本中可用。这将最多带来std::chrono::round1ns不同的结果。

如果您没有C ++ 17,但仍然想使用time_point_cast,请随时使用this one

此类型可以与round一起使用。

用积分算术精确地表示1/60

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_untilduration<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_pointsystem_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>>