【发布时间】:2014-01-21 13:47:45
【问题描述】:
我们的项目使用 boost::serialization 来序列化很多东西。 但是有些类型没有正确注册,在序列化它们时我们得到一个“未注册的类”错误 我已将问题缩小到 BOOST_CLASS_EXPORT_KEY,对于某些类型,它不会生成代码。 BOOST_CLASS_EXPORT_KEY 的作用是:
namespace boost {
namespace serialization {
template<>
struct guid_defined< T > : boost::mpl::true_ {};
template<>
inline const char * guid< T >(){
return K;
}
} /* serialization */
} /* boost */
所有被序列化的对象都继承自一个名为 Serializable 的基类。 序列化总是通过指向基类的指针来完成的。
这很好用,除了一种情况: 有一个类模板 SerializableList,它是一个 Serializable,它包含一个 T
列表template< typename T>
class SerializableList
{
...
std::vector<T> m_list;
template<class Archive>
void serialize( Archive & ar, const unsigned int /*version*/ )
{
ar & boost::serialization::base_object<businessObjects::Serializable>(*this);
ar & mList;
}
};
然后,我们在专用的 cpp 和 hpp 文件中声明此模板的每个实例化以促进序列化,如下所示:
hpp:
BOOST_CLASS_EXPORT_KEY( SerializableList<SomeT*> );
BOOST_CLASS_EXPORT_KEY( SerializableList<SomeOtherT*> );
BOOST_CLASS_EXPORT_KEY( SerializableList<AThirdT*> );
cpp:
BOOST_CLASS_EXPORT_IMPLEMENT( SerializableList<SomeT*> );
BOOST_CLASS_EXPORT_IMPLEMENT( SerializableList<SomeOtherT*> );
BOOST_CLASS_EXPORT_IMPLEMENT( SerializableList<AThirdT*> );
但是这些行中有一半不会在最终的可执行文件中生成可执行代码!如果我们在每一行都设置一个断点并运行,一半的断点会消失,留下的那些是工作类型(那些我们可以序列化的)。
例如,断点将保留在 SerializableList<SomeT*> 和 SerializableList<AThirdT*> 而不是 SerializableList<SomeOtherT*>。
顺便说一句,我们也尝试过直接调用boost::serialization::guid<T>(),虽然它可以正常工作,但可以说:
boost::serialization::guid<SerializableList<SomeT*> >() 返回密钥,
它不适合
boost::serialization::guid<SerializableList<SomeOtherT*> >() 调用默认实现...
那么是否存在编译器错误(我们使用 Visual C++ 2010 SP1),或者编译器是否有充分的理由忽略其中一些特化?
我忘了提,所有这些代码都在一个库中,该库与 exe 项目链接。我尝试过使用不同的 exe 项目,有时它可以工作,有时它不...编译选项是相同的...我真的 不知道发生了什么:'(
【问题讨论】:
-
您是否尝试显式实例化(缺失)类:
template class SerializableList<SomeOtherT*>;? -
"我忘了说,所有这些代码都在一个库中" 这可能是问题所在。它是静态库还是动态库? (我会尝试找到类似的问题,因为 IIRC 这个问题之前已经在 SO 上描述过)
-
boost docs: "在库代码中放置
BOOST_CLASS_EXPORT将无效,除非还包含归档类头文件。因此,在构建库时,应包含所有归档类的所有头文件他预计会使用它。或者,可以只包含 Polymoprhic 档案的标题。”(另见:stackoverflow.com/q/7875107/420683) -
另外,您可以尝试
/OPT:NOREF(属性->链接器->优化)或导出/导入BOOST_CLASS_EXPORT_IMPLEMENT创建的变量 -
如果您在评论中添加
@username,the user will be notified。将自动通知答案/帖子的所有者。 -- 如果幸运的话,您现在可能会发现 SSCCE 和您的实际程序之间存在差异的错误 :)(保持乐观)
标签: c++ templates visual-c++ boost template-specialization