Boost序列化库支持std::unique_ptr吗?

9
Boost序列化库是否支持std :: unique_ptr的序列化? 我尝试编译下面的代码,但如果包含 boost :: archive :: text_oarchive oa(ofs); oa << g; 这一行, 编译器(顺便说一句,使用gcc4.7和-std = c ++ 11标志)会抛出一个错误。 /usr/include/boost/serialization/access.hpp:118:9: error:‘class std :: unique_ptr’无成员名为‘serialize’
#include <iostream>
#include <memory>
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
class MyDegrees
{
public:
  void setDeg(int d){deg = d;}
  int getDeg()const {return deg;}
private:
  friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    { ar & deg; }
  int deg;
};
class gps_position
{
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    { ar & degrees; }
    std::unique_ptr<MyDegrees> degrees;
public:
    gps_position(): degrees(std::unique_ptr<MyDegrees>(new MyDegrees)){};
    void setDeg(int d){degrees->setDeg(d);}
    int getDeg() const {return degrees->getDeg();}
};
int main()
{
    std::ofstream ofs("filename");
    gps_position g;
    g.setDeg(45);
    std::cout<<g.getDeg()<<std::endl;
    {// compiler error, fine if commented out
        boost::archive::text_oarchive oa(ofs); oa << g;
    }
  return 0;
}

你使用的是哪个版本的Boost? - David Doria
1
@David,我不知道了,那是很久以前的事了。我已经实现了解决方案,在这个帖子下面你可以找到它。 - dodol
5个回答

9

我不太确定如何解释这个列表,但似乎支持在1.48之后添加。我正在使用1.58且已包括此功能。

#include <boost/serialization/unique_ptr.hpp>

然后它将按照以下方式工作:
#include <memory>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/unique_ptr.hpp>

#include <fstream>

class Point
{
public:
    Point() { }

    float x = 1.;
    float y = 2.;
    float z = 3.;

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

    template<class TArchive>
    void serialize(TArchive & archive, const unsigned int version)
    {
        archive & x;
        archive & y;
        archive & z;
    }
};

void ValidUniquePointer()
{
    std::unique_ptr<Point> p(new Point());

    std::ofstream outputStream("test.txt");
    boost::archive::text_oarchive outputArchive(outputStream);
    outputArchive << p;
    outputStream.close();

    // read from a text archive
    std::unique_ptr<Point> pointRead;
    std::ifstream inputStream("test.txt");
    boost::archive::text_iarchive inputArchive(inputStream);
    inputArchive >> pointRead;

    std::cout << pointRead->x << " " << pointRead->y << " " << pointRead->z << std::endl;

}

void NullUniquePointer()
{
    std::unique_ptr<Point> p;

    std::ofstream outputStream("test.txt");
    boost::archive::text_oarchive outputArchive(outputStream);
    outputArchive << p;
    outputStream.close();

    // read from a text archive
    std::unique_ptr<Point> pointRead;
    std::ifstream inputStream("test.txt");
    boost::archive::text_iarchive inputArchive(inputStream);
    inputArchive >> pointRead;

    if(pointRead != nullptr) {
        std::cout << pointRead->x << " " << pointRead->y << " " << pointRead->z << std::endl;
    }
    else {
        std::cout << "Pointer is null!" << std::endl;
    }

}

int main()
{
    ValidUniquePointer();
    NullUniquePointer();
    return 0;
}

我尝试了,但是出现了这个错误:class std::unique_ptr<snn::internal::Layer>没有名为serialize的成员。 - Matthieu H

8

正如pmr所提到的,我设法想出了以下解决方案,并且乍一看,一切都运作良好。希望有人能够发现它的用处:

#include <iostream>
#include <memory>
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
namespace boost { 
namespace serialization {

template<class Archive, class T>
inline void save(
    Archive & ar,
    const std::unique_ptr< T > &t,
    const unsigned int /*file_version*/
){
    // only the raw pointer has to be saved
    const T * const base_pointer = t.get();
    ar & BOOST_SERIALIZATION_NVP(base_pointer);
}
template<class Archive, class T>
inline void load(
    Archive & ar,
    std::unique_ptr< T > &t,
    const unsigned int /*file_version*/
){
    T *base_pointer;
    ar & BOOST_SERIALIZATION_NVP(base_pointer);
    t.reset(base_pointer);
}
template<class Archive, class T>
inline void serialize(
    Archive & ar,
    std::unique_ptr< T > &t,
    const unsigned int file_version
){
    boost::serialization::split_free(ar, t, file_version);
}
} // namespace serialization
} // namespace boost

class MyDegrees
{
public:
  void setDeg(int d){deg = d;}
  int getDeg()const {return deg;}
private:
  friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    { ar & deg; }
  int deg;
};
class gps_position
{
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    { ar & degrees;  }
    std::unique_ptr<MyDegrees> degrees;
public:
    gps_position(): degrees(std::unique_ptr<MyDegrees>(new MyDegrees)){};
    void setDeg(int d){degrees->setDeg(d);}
    int getDeg() const {return degrees->getDeg();}
};
int main()
{
    std::ofstream ofs("filename");
    gps_position g;
    g.setDeg(45);
    std::cout<<g.getDeg()<<std::endl;
    { boost::archive::text_oarchive oa(ofs); oa << g; }
    gps_position newg;
    {
        std::ifstream ifs("filename");
        boost::archive::text_iarchive ia(ifs);
        ia >> newg;
        std::cout<<newg.getDeg()<<std::endl;
    }
  return 0;
}

5
近期版本的boost序列化提供对所有std智能指针类型的支持。

这并没有回答问题。要对作者进行评论或请求澄清,请在其帖子下留言。-【来自审查】 - Andreas Louv
4
看起来这是对问题的答案,但如果能够给出具体版本号而不是含糊的“最近版本”,那将会更有帮助。任何比“Boost 1.32”更新的版本都可以吗? - jmunsch
@RobertRamey 这是在哪个版本的 Boost 中引入的? - David Doria
然而,这是有价值的信息。这样,如果人们卡在不支持std unique_ptr序列化的Boost序列化版本中,他们就不需要尝试编写自己的代码,只需复制/粘贴(如果可能的话)。 - dodol
Boost bug跟踪器上有一个问题,说已经添加了对此的支持:https://svn.boost.org/trac/boost/ticket/7688,但它没有说明是哪个版本。我正在使用1.58版本,它似乎不知道如何序列化std::unique_ptr。 - David Doria

5
Boost现在支持智能指针,您可以使用#include 头文件来使用Unique_Ptr。
 #include <boost/serialization/unique_ptr.hpp>

1

不,没有现成的适配器。您需要自己提供一个非侵入式的适配器。请参阅此处的教程以了解如何操作。


1
一个很好的起点是http://www.boost.org/doc/libs/1_51_0/libs/serialization/example/demo_auto_ptr.cpp。 - dodol
这是一个过时的答案,现在支持所有std智能指针。 - Kaaf
@Kaaf 随意提出建议,说明更改的具体版本。不幸的是,我不再是Boost(甚至不是C++用户)了,现在很难回答这个问题。 - pmr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接