持久化std :: chrono time_point实例然后将它们读回另一个相同类型的实例的正确方法是什么?
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t;
time_point_t tp = std::chrono::high_resolution_clock::now();
serializer.write(tp);
.
.
.
time_point_t another_tp;
serializer.read(another_tp);
写入/读取的调用,假设类型为time_point_t的实例可以某种方式转换为字节表示,然后可以写入磁盘或套接字等,或者从磁盘或套接字等读取。
Alf建议的可能解决方案如下:
std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();
//Generate POD to write to disk
unsigned long long ns0 = t0.time_since_epoch().count();
//Read POD from disk and attempt to instantiate time_point
std::chrono::high_resolution_clock::duration d(ns0)
std::chrono::high_resolution_clock::time_point t1(d);
unsigned long long ns1 = t1.time_since_epoch().count();
if ((t0 != t1) || (ns0 != ns1))
{
std::cout << "Error time points don't match!\n";
}
<击> 注意:上面的代码有一个错误,因为最终实例化的时间点与原始时间点不匹配。
在旧样式time_t的情况下,人们通常只是根据sizeof将整个实体写入磁盘,然后以相同的方式将其读回来 - 简而言之,新的std :: chrono类型的等价物是什么?
答案 0 :(得分:18)
从磁盘或套接字读取意味着您可能正在读取未执行写入的应用程序实例。在这种情况下,单独序列化持续时间是不够的。
time_point
自未指定的纪元以来的duration
时间。这个时代可能是任何事物。在我的计算机上,std::chrono::high_resolution_clock
的时代就是计算机启动时的时代。即此时钟报告自启动以来的纳秒数。
如果一个应用程序写入time_since_epoch()。count(),计算机将重新启动,然后另一个(甚至是同一个)应用程序将其读回,读入值没有任何意义,除非您碰巧以某种方式知道靴子之间的时间。
为了可靠地序列化time_point
,必须安排作者和读者就某个时代达成一致,然后确保time_point
写入和读取与该时期有关。例如,人们可能会安排使用POSIX时代:1970年的新世界。
事实证明,我所知道的每个std::chrono::system_clock
实现都使用Unix time,这是从1970年新年开始测量的近似UTC。然而,我知道{{1}没有共同的时代}。
只有当你能以某种方式确保读者和作者时钟在一个共同的时代上达成一致时,你才能将time_point序列化为持续时间。
答案 1 :(得分:6)
time_point
构造函数需要duration
,您可以从成员duration
获得time_since_epoch
。因此,问题减少为序列化duration
值。并且duration
有一个带有多个刻度的构造函数,以及一个产生刻度数的成员函数count
。
这一切只是通过谷歌搜索std::chrono::time_point
并查看cppreference文档谷歌让我着迷。
阅读 documentation 通常是一个好主意。
附录:一个例子。
#include <chrono>
#include <iostream>
#include <typeinfo>
using namespace std;
auto main() -> int
{
using Clock = chrono::high_resolution_clock;
using Time_point = Clock::time_point;
using Duration = Clock::duration;
Time_point const t0 = Clock::now();
//Generate POD to write to disk
Duration::rep const ns0 = t0.time_since_epoch().count();
//Read POD from disk and attempt to instantiate time_point
Duration const d(ns0);
Time_point const t1(d);
cout << "Basic number type is " << typeid( ns0 ).name() << "." << endl;
if( t0 != t1 )
{
cout << "Error time points don't match!" << endl;
}
else
{
cout << "Reconstituted time is OK." << endl;
}
}
使用Visual C ++ 12.0,报告的基本类型为__int64
,即long long
,而在Windows中使用g ++ 4.8.2时,报告的类型为x
,这可能意味着相同。< / p>
对于两个编译器,重构时间与原始时间相同。
附录:作为评论中的noted by Dina,从C ++ 14开始,C ++标准没有指定纪元,因此可以跨机器或使用不同的时钟有必要添加额外的步骤来规范化序列化数据的时期,例如最自然的是Posix time,即1970年1月1日星期四00:00:00世界协调时间(UTC)以来的时间。