如何让 boost::serialization 工作?

Posted

技术标签:

【中文标题】如何让 boost::serialization 工作?【英文标题】:how to get boost::serialization to work? 【发布时间】:2014-01-16 07:24:38 【问题描述】:

我正在开发 ubuntu 12.04LTS 并使用 clang 3.4。

我有一个 CMake 项目并想使用 boost 序列化库。我从 SourceForge 下载了 boost 1.55.0。

我的项目文件夹树如下所示:

MyProject
    |    Source
    |       |    main.cpp
    |       |    CMakeLists.txt
    |    Build
    |    Libraries
    |       |    Boost1p55p0
    |       |         |    boost
    |       |         |    ...other boost data
    |       |         |    build
    |       |         |       |    include
    |       |         |       |    lib

所以在Boost1p55p0 目录中我创建了一个新目录build,所以引导程序看起来像:

./bootstrap.sh --prefix=build/

然后我做了

./b2

./b2 install

所以最小的不工作示例是:

CMakeLists.txt:

cmake_minimum_required (VERSION 2.6)

set( CMAKE_C_COMPILER clang )
set( CMAKE_CXX_COMPILER clang++ )
set( CMAKE_LINKER llvm-link )

project (Test)
include_directories( $PROJECT_SOURCE_DIR ../Libraries/Boost1p55p0/build/include )

set( sources $sources main )

add_executable(Test $sources)

set( OperatingSystem "Linux" )
set( CMAKE_CXX_FLAGS "-std=c++11" )

find_library( PATH_TO_BoostSerialization boost_serialization ../Libraries/Boost1p55p0/build/lib/ )

target_link_libraries (Test $PATH_TO_BoostSerialization)

main.cpp(来自tutorial,但带有 xml 档案):

#include <fstream>
#include <string>

// include headers that implement a archive in simple text format
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>

/////////////////////////////////////////////////////////////
// gps coordinate
//
// illustrates serialization for a simple type
//
class gps_position

    private:
        friend class boost::serialization::access;

        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        
            ar & degrees;
            ar & minutes;
            ar & seconds;
        
        int degrees;
        int minutes;
        float seconds;
    public:
        gps_position();
        gps_position(int d, int m, float s) :
            degrees(d), minutes(m), seconds(s)
;

int main() 
    std::string inFileName = "testIn.xml";
    std::string outFileName = "testOut.xml";
    // create and open a character archive for output
    std::ofstream ofs(outFileName);

    // create class instance
    const gps_position g(35, 59, 24.567f);

    // save data to archive
    
        boost::archive::xml_oarchive oa(ofs);
        // write class instance to archive
        oa << g;
    

    return 0;

现在我得到以下编译器错误:

[cut off directory tree here]Boost1p55p0/build/include/boost/archive/basic_xml_oarchive.hpp:92:9: error: no matching function for call to
  'assertion_failed'
    BOOST_MPL_ASSERT((serialization::is_wrapper< T >));
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[cut off directory tree here]Boost1p55p0/build/include/boost/mpl/assert.hpp:287:11: note: expanded from macro 'BOOST_MPL_ASSERT'
      boost::mpl::assertion_failed<false>( \

我不知道错误在哪里。如果我知道,我会很高兴。

在此先感谢

【问题讨论】:

【参考方案1】:

啊,我刚刚注意到你在这里提到了唯一重要的一点,隐藏在一个小侧面:

main.cpp(来自教程,但带有 xml 档案)

Xml 档案的元素需要名称

Name-Value Pairs

XML 档案有一种特殊的情况。 XML 格式具有嵌套结构,可以很好地映射到序列化系统使用的“递归类成员访问者”模式。但是,XML 与其他格式的不同之处在于它需要为每个类数据成员命名。我们的目标是将此信息添加到类序列化规范中,同时仍允许序列化代码与任何存档一起使用。

我们的解决方案是将要序列化的类成员包装在 name-value-pair 中。此结构在 nvp.hpp 中定义。它只是对数据成员的引用以及指向对应于 XML 名称的 const char * 的指针。它实现了名称-值对的默认序列化函数。此默认操作只是忽略项目名称并以正常方式序列化数据值。对于没有为名称-值对做出任何特殊规定的归档类,这是在名称-值对被序列化时将调用的操作。因此,将数据值包装成名称-值对在与没有为此包装器提供特殊规定的档案一起使用时将无效。

看,看demo_xml.cpp,加:

template<class Archive>
void serialize(Archive & ar, const unsigned int version)

    ar & BOOST_SERIALIZATION_NVP(degrees);
    ar & BOOST_SERIALIZATION_NVP(minutes);
    ar & BOOST_SERIALIZATION_NVP(seconds);

boost::archive::xml_oarchive oa(ofs);
// write class instance to archive
oa << BOOST_SERIALIZATION_NVP(g);

Live on Coliru

输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="10">
<g class_id="0" tracking_level="0" version="0">
    <degrees>35</degrees>
    <minutes>59</minutes>
    <seconds>24.566999</seconds>
</g>
</boost_serialization>

【讨论】:

谢谢。现在发布的代码有效。但我没有忘记提及:main.cpp (from the tutorial but with xml archives) ;)。但现在我想更进一步并补充说:gps_position newg; std::ifstream ifs(outFileName); boost::archive::xml_iarchive ia(ifs); ia &gt;&gt; newg; 。但是这个编译失败并出现完全相同的错误消息。那里有什么问题?现在Coliru ;) @Rico-E 我终于注意到隐藏得很好的评论并且已经编辑了答案:) 我同意:它隐藏得很好;)抱歉,我根本不知道这是重要的一点。但是你能看看我的第一条评论,因为现在阅读 xml 档案失败了。我什至学会了使用 Coliru :) 嗯,如果它是完全相同的消息,那么,通常它是完全相同的问题:) 我已经修改了答案:coliru.stacked-crooked.com/a/7c21b376a5c468b3 太棒了!非常感谢!

以上是关于如何让 boost::serialization 工作?的主要内容,如果未能解决你的问题,请参考以下文章

使用 boost::serialization 时如何刷新文件缓冲区?

如何抑制 boost serialization::archive 中的额外信息?

如何为 boost::serialization 指定一个 nvp 包装器?

使用 boost::serialization 保存数据时出现 Seg 错误

找不到 boost::serialization 的成员

我可以告诉 Boost.MPI 哪个类版本与 Boost.Serialization 一起使用吗?