【问题标题】:boost serialization std::unique_ptr support提升序列化 std::unique_ptr 支持
【发布时间】:2012-10-06 14:04:30
【问题描述】:

boost 序列化库是否支持 std::unique_ptr 的序列化? 我试图编译下面的代码,但如果我包括 boost::archive::text_oarchive oa(ofs); oa 行,

编译器(btw gcc4.7 with -std=c++11 flag)抛出错误

/usr/include/boost/serialization/access.hpp:118:9: 错误:‘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 我不知道,那是很久以前的事了。我已经实现了您可以在此线程中找到的解决方案。

标签: c++ boost c++11 boost-serialization


【解决方案1】:

我不确定如何解释 this list,但似乎在 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&lt;snn::internal::Layer&gt;’ has no member named ‘serialize’
【解决方案2】:

正如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;
}

【讨论】:

    【解决方案3】:

    最新版本的 boost 序列化支持所有 std 智能指针类型。

    【讨论】:

    • 这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review
    • @dev-null 看起来这是对这个问题的回答,但是如果不是模糊的“最新版本”而是确切的版本,那会很有帮助?有什么比“Boost 1.32”更新的吗?
    • @RobertRamey 哪个版本的 Boost 引入了这个?
    • 不过,这是很有价值的信息。这样人们就不需要尝试编写自己的代码,只要 c/p(当然,如果可能的话)如果他们坚持使用不支持 std unique_ptr 序列化的 Boost 序列化版本
    • Boost 错误跟踪器上有一个问题,表明已添加对此的支持:svn.boost.org/trac/boost/ticket/7688,但没有说明是哪个版本。我使用的是 1.58,它似乎不知道如何序列化 std::unique_ptr 。
    【解决方案4】:

    Boost 现在支持智能指针,您可以为 Unique_Ptr #include 头文件。

     #include <boost/serialization/unique_ptr.hpp>
    

    【讨论】:

      【解决方案5】:

      不,没有开箱即用的适配。您需要自己提供一个非侵入式适配器。请参阅tutorial here 了解如何执行此操作。

      【讨论】:

      • 这是一个过时的答案,现在支持所有标准智能指针。
      • @Kaaf 随时建议使用更改的特定版本进行编辑。不幸的是,我不再是 Boost(甚至 C++ 用户),现在很难回答这个问题。
      猜你喜欢
      • 2016-03-05
      • 1970-01-01
      • 1970-01-01
      • 2020-04-17
      • 2012-11-25
      • 1970-01-01
      • 2013-01-22
      • 2011-02-26
      • 1970-01-01
      相关资源
      最近更新 更多