【发布时间】:2021-08-06 21:52:51
【问题描述】:
我有一个设备,它以整数秒和小数秒为单位报告时间。对于这个特定的设备,时钟运行在 256MHz。我已经定义了我在持续时间和时间点中使用的自定义分辨率:
using Res = std::chrono::duration<uint64_t, std::ratio<1, 256'000'000>>;
(除非它是相关的,我宁愿不争论 uint 与 int)。
此分辨率足以表示自 1970 年以来的时间,溢出时间约为 2763。
给定,
#include <iostream>
#include <chrono>
int main() {
using Res = std::chrono::duration<uint64_t, std::ratio<1, 256'000'000>>;
using namespace std::chrono;
using TimePoint = time_point<system_clock, Res>;
auto s_now = system_clock::now();
auto simple = time_point_cast<Res>(s_now);
auto s_sec = duration_cast<seconds>(s_now.time_since_epoch());
auto hard = TimePoint(Res(s_sec));
hard += duration_cast<Res>(s_now.time_since_epoch() - s_sec);
std::cout << "s_now " << s_now.time_since_epoch().count() << "\t" << s_sec.count() << "\n"
<< "simple " << simple.time_since_epoch().count() << "\t" << duration_cast<seconds>(simple.time_since_epoch()).count() << "\n"
<< "hard " << hard.time_since_epoch().count() << "\t" << duration_cast<seconds>(hard.time_since_epoch()).count() << "\n"
;
return 0;
}
那么simple 不等于hard。输出可能是这样的:
s_now 1628286679505051812 1628286679
simple 121693484773940438 475365174
hard 416841389953293263 1628286679
发生的情况是 time_point_cast overflows int 代表 system_clock::duration。
基于https://stackoverflow.com/a/51226923/9220132,这似乎是合法和道德的,但它的味道并不好。这种限制太容易产生错误来源。
如果有一种方法可以让我定义转换为我的高分辨率类型的实现,以便防止溢出,那将是理想的。知道使用自定义辅助函数而不是强制转换只是自找麻烦,因为有人会忘记一些时间,并且该错误可能会在生产中被忽视。
【问题讨论】:
-
我不确定我是否理解你的问题,但是在
std中添加一些东西是非常非法的,也就是 UB,除非明确允许 stackoverflow.com/questions/37541022/… -
明白了。但是,在某些情况下,为用户定义的类型提供模板特化是合法的。我希望答案就在那个方向。
-
是的,
std::hash允许,但必须允许。可以尝试在 cppreference.com 上找到它。否则必须阅读标准,即免费草案,您可以通过该网站的常见问题解答找到。我会期待但它的就寝时间对我来说。 -
@Superlokkus 只要涉及到用户定义的类型,在
std中进行特化是完全可以的(std::hash<user_defined_type>是一个常用的例子)——我不确定这是否适用于虽然这种情况,但它可能。 -
但是,
std::chrono::duration<uint64_t, std::ratio<1, 256'000'000>>不是用户定义的类型,与(比如说)std::vector<int>一样。