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”。这意味着仅在整个程序中通过指针序列化类实例时才跟踪类实例。现在从相同地址进行的多次保存仅导致第一个