boost::serialization中为泛型结构体(类)标注版本号

来源:互联网 发布:星际争霸 知乎 编辑:程序博客网 时间:2024/05/01 21:34

    我使用boost::serialization主要是用在软件的工程管理中,在工程管理中版本兼容是很重要的,比如要保证一个比较旧的工程在最新版的软件里仍然可以被导入。

    boost中可以使用BOOST_CLASS_VERSION这个宏为某个结构体(类)标记版本号(版本号最大是256)。但在使用时发现这个宏有一个局限,就是不能为泛型结构体(类)标记。比如有以下支持序列化的结构体:

template< typename T >struct PointEx{float X;float Y;T flag;template< typename Archive >void serialize( Archive &ar, const unsigned int version ){ar & BOOST_SERIALIZATION_NVP( X );ar & BOOST_SERIALIZATION_NVP( Y );ar & serialization::make_nvp( "flag", flag );}};BOOST_CLASS_VERSION( PointEx, 13 );
    这样会产生一个编译错误:

    于是查看BOOST_CLASS_VERSION的详细定义(在boost/serialization/version.hpp中):

#define BOOST_CLASS_VERSION(T, N)                                      \namespace boost {                                                      \namespace serialization {                                              \template<>                                                             \struct version<T >                                                     \{                                                                      \
    // 中间省略                                                        \}                                                                      \
发现它根据类名定义了一个泛型结构体version<T>,在version内部记录了版本号N的相关内容。整个宏中与我们定义的类PointEx相关的就version<T >这一句,那么如果T是泛型的,这样的定义当然编译不通了,于是凭直觉我尝试做出如下新的宏定义:

#define BOOST_CLASS_VERSION_GENERIC( T, N )                               \namespace boost {                                                         \namespace serialization {                                                 \template< typename U >                                                    \struct version< T< U > >                                                  \{                                                                         \    typedef mpl::int_< N > type;                                          \    typedef mpl::integral_c_tag tag;                                      \    BOOST_STATIC_CONSTANT( int, value = version::type::value );           \    BOOST_MPL_ASSERT( ( boost::mpl::less< boost::mpl::int_< N >,          \boost::mpl::int_< 256 > > ) );                                    \};                                                                        \} }                                                                       \
应用到PointEx后果然可以!类似的我们还可以定义更多的诸如template< typename U1,typename U2  > struct version< T< U1, U2 > >这样的宏方便其他泛型使用。


完整的测试代码:

#include <stdio.h>#include <fstream>#include <boost/archive/xml_oarchive.hpp>#include <boost/archive/xml_iarchive.hpp>#include <boost/serialization/nvp.hpp>#include <boost/serialization/version.hpp>using namespace std;using namespace boost;#define BOOST_CLASS_VERSION_GENERIC( T, N )                               \namespace boost {                                                         \namespace serialization {                                                 \template< typename U >                                                    \struct version< T< U > >                                                  \{                                                                         \    typedef mpl::int_< N > type;                                          \    typedef mpl::integral_c_tag tag;                                      \    BOOST_STATIC_CONSTANT( int, value = version::type::value );           \    BOOST_MPL_ASSERT( ( boost::mpl::less< boost::mpl::int_< N >,          \boost::mpl::int_< 256 > > ) );                                    \};                                                                        \} }                                                                       \template< typename T >struct PointEx{float X;float Y;T flag;template< typename Archive >void serialize( Archive &ar, const unsigned int version ){cout << version << endl;ar & BOOST_SERIALIZATION_NVP( X );ar & BOOST_SERIALIZATION_NVP( Y );ar & serialization::make_nvp( "flag", flag );}};BOOST_CLASS_VERSION_GENERIC( PointEx, 13 );int main(int argc, char* argv[]){PointEx< int > _Pnt = { 3.3f, 5.4f, 123 };cout << "Serialize version : ";ofstream ofile( "proj.dat" );archive::xml_oarchive oa( ofile );oa << serialization::make_nvp( "Point", _Pnt );ofile.close();cout << "Deserialize version : ";ifstream ifile( "proj.dat" );archive::xml_iarchive ia( ifile );PointEx< int > _PntD;ia >> serialization::make_nvp( "Point", _PntD );ifile.close();return 0;}






0 0
原创粉丝点击