无法使 C++ Boost 指针序列化工作

Can't get C++ Boost Pointer Serialization to work

此问题与列为重复的问题不同: Boost c++ serializing a char * 我没有使用 shared_ptr,我可以完全访问我的 类.

的内部结构

我能找到的最接近的响应是在 Store a vector of pointers to custom objects to file 中,这是我通过搜索编译器错误找到的。

然而,那里给出的答案并不清楚,至少对我来说是这样。它指向 boost 文档,这表明我在此处列出的简单代码应该可以工作。在对通过指针序列化对象的所有内务处理进行分类后,boost 文档这样说。

This serialization library addresses all of the above considerations.

如果我必须一次写一个 char[] 一个字符,或者如果我必须取消引用容器中的所有指针对象并将它们分解为它们的构成 POD 部分,首先将它们的大小(以字节为单位)写入流,为了用boost序列化,那么使用boost似乎没有多大意义。这是大部分工作。创建文本输出流并将字节注入其中是微不足道的。

我并不是说我对文档的阅读理解有问题,但根据我对所读内容的理解,下面的代码片段应该有效。但是,此代码会发出以下编译器错误。所以,我一定是遗漏了一些东西,但我就是看不到它,所以这就是我寻求帮助的原因。

简单地指出下面代码片段中的失败点怎么样?或者,更好的是,提供一个有效的片段?

/usr/include/boost/serialization/access.hpp:118:9: error: ‘class boost::ptr_vector<std::basic_string<char> >’ has no member named ‘serialize’
         t.serialize(ar, file_version);
         ^
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

class A {
public:
        A(){}

        char c;
        char *name;

        friend boost::serialization::access;
        template<class Archive>

        void serialize(Archive& ar, unsigned version) 
        {
                ar &  name;
        }
};

main()
{
        A a;
        a.name = (char *)"this is a test";

        std::ofstream ofs("table.txt");
        boost::archive::text_oarchive os(ofs);
        os << a;
}

我可以序列化 int、char,甚至是 STL 类型,但我不能用指针序列化任何东西。例如,我可以序列化 std::vector<std::string>,但如果我尝试序列化 std::vector<std::string *>,我将得到编译器错误。

If I must write a char[] one character at a time, or if I must dereference all pointer objects in a container and break them down to their constituent POD parts, writing their sizes in bytes to the stream first, in order to serialize with boost, then there doesn't seem to be much point in using boost.

是的。但是您正在尝试序列化一个指针。指向 char 的指针应该序列化为什么? T* 肯定应该序列化一个动态分配的 T,不是吗?所以你会期望序列化单个 char 除非 namenullptr?

或者您希望对每个序列化的字符进行完整的 object 跟踪?

这里的重点是您选择了原始类型的原始指针。指针缺少必要的信息。因此,您有责任添加信息。如果您发现 乏味 ,您可以改用 C++ 类型。

请注意,无论如何,这在 C++03 及更高版本中是不合法的:

a.name = (char *)"this is a test";

char const(&)[15]char * 的静态转换会删除 const 资格。您的编译器无论如何都应该拒绝此代码。

这是我的看法(使用 std::string):

#include <boost/serialization/string.hpp>
#include <boost/archive/text_oarchive.hpp>

class A {
  public:
    std::string name;
    template <class Archive> void serialize(Archive &ar, unsigned) {
        ar & name;
    }
};

int main() {
    A a { "this is a test" };
    boost::archive::text_oarchive os(std::cout);
    os << a;
}

顺便说一句,链接的重复问题的标题与您在此处尝试执行的操作完全匹配:Boost c++ serializing a char * 并且接受的答案显示完全相同的解决方案。

如果你真的坚持,你当然可以去mud-wrestle一些C-style没有荣耀的代码:

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <cstring>
#include <cstdlib>

class A {
  public:
    A(char const* sz = nullptr) : name(sz? strdup(sz) : nullptr) {}
    A(A const&) = delete;
    A& operator=(A const&) = delete;

    ~A() { free(name); }

  private:
    char* name;

    template <class Archive> void save(Archive &ar, unsigned) const {
        bool have_name = name;
        ar & have_name;

        if (have_name)
        {
            size_t len = strlen(name);
            ar & len;
            ar & boost::serialization::make_binary_object(name, len);
        }
    }

    template <class Archive> void load(Archive &ar, unsigned) {
        bool have_name = name;
        ar & have_name;

        if (!have_name)
        {
            free(name);
            name = nullptr;
        } else
        {
            size_t len = 0;
            ar & len;

            name = static_cast<char*>(realloc(name, len));
            ar & boost::serialization::make_binary_object(name, len);
        }
    }

    friend class boost::serialization::access;
    BOOST_SERIALIZATION_SPLIT_MEMBER()
};


int main() {
    A a { "this is a test" };
    boost::archive::text_oarchive os(std::cout);
    os << a;
}

但是,所有这些让您获得的收益是 6 倍的代码、残缺的值语义、完全放弃的关注点分离、大量潜在的错误(您有没有想过 name==null 和 [=23= 之间的区别? ]? 目前我的实现 employs unspecified (implementation-defined) behaviour。我会把它作为练习留给你 reader,在这里想出密封处理)并且......甚至没有可读的字符串输出。

Yes, of course make_array would give you 14 116 104 105 115 32 105 115 32 97 32 116 101 115 116 instead of dGhpcyBpcyBhIHRlc3Q=, but that's horrifically storage inefficient and still not human readable.