为什么以下函数不会编译,并显示错误
cannot convert from 'std::chrono::time_point<std::chrono::steady_clock,std::chrono::duration<double,std::nano>>' to 'std::chrono::time_point<std::chrono::steady_clock,std::chrono::steady_clock::duration>'
#include <chrono>
typedef std::chrono::high_resolution_clock::time_point TimePoint;
typedef std::chrono::duration<double, std::ratio<86400>> JulianDays;
TimePoint JulianDaysToUTC(const JulianDays& days)
{
static const JulianDays EquivalentJulianYearInDays(2451545.0);
static const JulianDays LeapSecondCorrection(0.0008);
static const TimePoint CorrectedEpoch = TimePoint() - EquivalentJulianYearInDays + LeapSecondCorrection;
return CorrectedEpoch + days;
}
注意:TimePoint()
代替了返回TimePoint
的函数,但该返回值与/不相关。
将其修改为使用整数持续时间可以编译,但是我丢失了小数日部分,这是不希望的。
#include <chrono>
typedef std::chrono::high_resolution_clock::time_point TimePoint;
typedef std::chrono::duration<int, std::ratio<86400>> Days;
typedef std::chrono::duration<double, std::ratio<86400>> JulianDays;
TimePoint JulianDaysToUTC(const JulianDays& days)
{
using std::chrono::duration_cast;
static const JulianDays EquivalentJulianYearInDays(2451545.0);
static const JulianDays LeapSecondCorrection(0.0008);
static const TimePoint CorrectedEpoch = TimePoint() - duration_cast<Days>(EquivalentJulianYearInDays) + duration_cast<Days>(LeapSecondCorrection);
return CorrectedEpoch + duration_cast<Days>(days);
}
答案 0 :(得分:1)
<chrono>
库的设计使截断错误不会隐式发生。这是因为截断错误很容易发生,并且经常导致信息意外丢失。
错误消息:
无法从
time_point<steady_clock, duration<double,std::nano>>
进行转换 到time_point<steady_clock, steady_clock::duration>
表示已经尝试了从分数纳秒(基于双精度)到整个纳秒(基于整数)的隐式转换,但不允许这样做。事实证明,每个steady_clock::duration
都是十亿分之一秒,尽管未指定。
如果要截断(如本例所示),则可以使用duration_cast
或time_point_cast
截断为零。在C ++ 17中,添加了floor
,ceil
和round
截断模式。
这是执行库拒绝执行的截断强制转换的最直接方法:
#include <chrono>
typedef std::chrono::high_resolution_clock::time_point TimePoint;
typedef std::chrono::duration<double, std::ratio<86400>> JulianDays;
TimePoint JulianDaysToUTC(const JulianDays& days)
{
static const JulianDays EquivalentJulianYearInDays(2451545.0);
static const JulianDays LeapSecondCorrection(0.0008);
static const TimePoint CorrectedEpoch =
std::chrono::time_point_cast<TimePoint::duration>(
TimePoint() - EquivalentJulianYearInDays + LeapSecondCorrection);
return std::chrono::time_point_cast<TimePoint::duration>(CorrectedEpoch + days);
}
第一次强制转换是必需的,因为表达式TimePoint() - EquivalentJulianYearInDays + LeapSecondCorrection
具有类型time_point<high_resolution_clock, duration<double, nano>>
(浮点纳秒time_point),而目的地类型是基于整数的纳秒time_point。同上进行第二次转换。
auto
可用于清除这段代码,并避免其中一种转换:
#include <chrono>
typedef std::chrono::high_resolution_clock::time_point TimePoint;
typedef std::chrono::duration<double, std::ratio<86400>> JulianDays;
TimePoint JulianDaysToUTC(const JulianDays& days)
{
static const JulianDays EquivalentJulianYearInDays(2451545.0);
static const JulianDays LeapSecondCorrection(0.0008);
static const auto CorrectedEpoch = TimePoint() -
EquivalentJulianYearInDays + LeapSecondCorrection;
return std::chrono::time_point_cast<TimePoint::duration>(CorrectedEpoch + days);
}
现在CorrectedEpoch
是一个基于双精度的纳秒time_point,但是该细节对于您的算法而言并不重要。
此外,Nicol Bolas对high_resolution_clock
可疑使用的评论也是有根据的。如果您从未将TimePoint
与来自high_resolution_clock::time_point
的{{1}}混合使用,则您的代码可能会起作用。但是,使用记录在案的2000-01-01 12:00:00 UTC纪元创建自己的自定义时钟会更安全。然后,任何意外的混合都会在编译时被捕获。