4.2 Serializable Concept(3)

Compile Time Warnings and Errors

一些序列化特性可能与其他特性发生冲突。有时,这些冲突会导致错误的行为(例如,创建无法读取的归档),而其他时候它们代表了库用户可能存在的概念错误,可能导致意外行为。在尽可能的情况下,这些冲突在编译时被检测到,然后生成错误(BOOST_STATIC_ASSERT)或警告(BOOST_STATIC_WARNING)。它们以一种依赖于编译器的方式生成,应该显示出一条实例化链,直到检测到错误/警告的点。如果没有这个能力,将会很难追踪到库使用中的错误或意外行为。以下是被检测到的冲突列表:

object_level - error

此错误捕获试图序列化其实现级别设置为non_serializable的类型的尝试。

object_versioning - error

出于效率原因,可能会为某种类型分配一个不包括类型信息的序列化级别,这将阻止为该类型分配新版本号的尝试。在这种情况下,此错误会捕获尝试分配版本号的操作。这必定是用户的错误。

object_tracking - warning

以下代码在编译时会显示一条消息:

T t;
ar << t;

除非将tracking_level序列化特性设置为"track_never"。以下代码将无问题地编译通过:

const T t;
ar << t;

同样,以下代码将在编译时引发错误:

T * t;
ar >> t;

如果tracking_level序列化特性设置为track_never。这个案例说明了此消息的功能。最初,它是由Peter Dimov在邮件列表中用作示例的。

class construct_from { ... };
void main(){ ... Y y; construct_from x(y); ar << x; }

假设上面的消息没有显示,而是直接使用了这段代码。这个示例编译并执行正常。之所以没有进行跟踪,是因为construct_from从未通过指针进行序列化。现在,过了一段时间,第二个程序员(2)出现并进行了一次增强。他希望归档可以成为一种日志。

void main(){ 
    ... 
    Y y; 
    construct_from x(y); 
    ar << x; 
    ... 
    x.f(); // 更改x
    ... 
    ar << x;
}

再次没有问题。他在归档中得到了两个不同的副本,每个副本都是不同的。也就是说,他得到了他期望的完全相符,自然是高兴的。

现在过了一段时间,第三个程序员(3)看到了construct_from并说:“哦,很酷,正是我需要的。”他在一个完全不相关的模块中编写了一个函数(项目如此庞大,以至于他甚至没有意识到原始用法的存在),并编写了如下内容:

class K { 
    shared_ptr <construct_from> z; 
    template <class Archive> 
    void serialize(Archive & ar, const unsigned version){ 
        ar << z; 
    } 
}; 

他构建并运行程序,测试了他的新功能。一切都运行得很顺利,他很高兴。

事情一如既往地顺利进行。一个月过去了,人们发现在加载上个月制作的存档(读取日志)时出现了问题。事情不正常。第二个日志条目总是与第一个相同。在一系列长时间的、日益尖锐的电子邮件交流之后,人们发现程序员(3)无意中破坏了程序员(2)的代码。这是因为通过指针进行序列化,现在跟踪“日志”对象。这是因为默认的跟踪行为是“track_selectively”。这意味着仅在整个程序中通过指针序列化类实例时才跟踪类实例。现在从相同地址进行的多次保存仅导致第一个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值