获取用于非侵入性提升序列化C++的私有数据成员
Get private data members for non intrusive boost serialization C++
我已经尝试为我的非成员serialize()
函数提供类A
的getter,因为从成员的访问是私有的。
template<typename T>
class A
{
public:
A(const T& id) : m_id(id) {}
T& getRef() { return m_id; } // not giving good results
T getId() { return m_id; } // not giving good results
const T& getRef() const { return m_id; } // not giving good results
private: // I would like to keep it private
T m_id;
}
namespace boost { namespace serialization {
template<class Archive,typename T>
void serialize(Archive &ar, A &a, const unsigned int version)
{
// ar &BOOST_SERIALIZATION_NVP(a.m_id); // I would like to avoid that it works if m_id is public
ar &BOOST_SERIALIZATION_NVP(a.GetRef()); // I want this !
}
}}
// and later I use
std::ofstream ofs("test.xml");
boost::archive::xml_oarchive oa(ofs);
A<int> a(42);
oa << BOOST_SERIALIZATION_NVP(a);
不幸的是,当我尝试使用getter GetRef()
或GetId()
时,执行一直告诉我uncaught exception of type boost::archive::xml_archive_exception - Invalid XML tag name
如果我在m_id
公开时直接访问它,效果会很好。
有什么好方法吗?
-
你可以使用好的老式朋友:
在Coliru上直播
template <typename T> class A { public: A(const T &id) : m_id(id) {} private: template <typename Ar, typename U> friend void boost::serialization::serialize(Ar&,A<U>&,const unsigned); T m_id; }; namespace boost { namespace serialization { template <class Archive, typename T> void serialize(Archive &ar, A<T> &a, const unsigned int) { ar & BOOST_SERIALIZATION_NVP(a.m_id); } } }
-
您可以使用
getRef()
方法。这个- 不需要朋友(侵扰性较小(
- 需要
make_nvp
(因为不能将a.getRef()
用作XML元素名称
可悲的是,引用getter以一种可怕的方式破坏了封装。我个人更愿意首先公开
m_id
。在Coliru上直播
template <typename T> class A { public: A(const T &id) : m_id(id) {} T& getRef() { return m_id; } T const& getRef() const { return m_id; } private: T m_id; }; namespace boost { namespace serialization { template <class Archive, typename T> void serialize(Archive &ar, A<T> &a, const unsigned int) { ar & boost::serialization::make_nvp("m_id", a.getRef()); } } }
奖励积分:
-
您可以使用"pimpl"样式的结构。您可以在
A<>
:中转发声明一个结构template <typename T> class A { public: struct access; A(const T &id) : m_id(id) {} private: T m_id; };
这比
getRef()
方法侵入性更小,后者只是一路破坏封装。现在,您可以将私有访问隐藏在这个类中:namespace boost { namespace serialization { template <class Archive, typename T> void serialize(Archive &ar, A<T> &a, const unsigned int version) { A<T>::access::serialize(ar, a, version); } } }
当然,您仍然需要实现它,但这可以在单独的头中完成,并且不会影响类a<>(或其任何专业(:
template <typename T> struct A<T>::access { template <class Archive> static void serialize(Archive &ar, A<T> &a, const unsigned int) { ar & BOOST_SERIALIZATION_NVP(a.m_id); } };
查看Coliru直播以及
仅用于其他信息:为了从获得第一个解决方案,正在工作:
您需要一个朋友的前向分离方法,如下所示:
// Boost
#include <boost/serialization/access.hpp>
class ClassB;
namespace boost{
namespace serialization {
template <typename Ar> void serialize(Ar&,ClassB&,const unsigned);
}
}
class ClassB: public ClassA{
private:
template <typename Ar> friend void boost::serialization::serialize(Ar&,ClassA&,const unsigned);
public:
ClassA();
virtual ~ClassA();
};
我花了一段时间才开始工作。
干杯
第一个解决方案的补充信息:
该解决方案需要两阶段查找和/或依赖于参数的查找。不幸的是,微软风投公司还没有完全支持这一点。
在VS Community 2019 16.1.6和boost 1.70中编译此代码会导致一个模糊错误:
Error C2063 'boost::serialization::serialize': not a function
尽管一致性模式是通过/permission-标志启用的,并且选择了最新的语言标准/std::c++latest,如本MSVC博客文章所述。
在友元声明中添加typename限定符可以解决问题:
template <typename Ar, typename U> friend void boost::serialization::serialize(typename Ar&, A<U>&, const unsigned);
更有趣的是令人沮丧的是:
若类A不是一个模板化的类,那个么它无论如何都不起作用,和上面的错误相同。。。示例代码:http://coliru.stacked-crooked.com/a/ecfbb39d5975d753
- 如何在C++中序列化结构数据
- 序列化,没有库的整数,得到奇怪的结果
- 如何知道QDataStream不能反序列化某些内容
- 如何使用Python从C++中读取谷物序列化数据
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 带有Protobuf序列化的C++Hazelcast:字符串不是UTF-8格式的
- 自定义对象的dlib序列化在gcc中失败
- C++boost序列化多态性问题
- 增强基于 XML class_id的反序列化
- 提升反序列化对象具有 nan 或 -nan 值
- 在 cpp 中的平面缓冲区中序列化对象
- 每次进行继承时都需要提升::序列化::base_object吗?
- 如何在 c++ 非托管代码中反序列化 byte[] 的 json 字符串?
- 提升序列化 1:73 的向后兼容性问题
- 将 boost 序列化对象的 asio::streambuf 表示转换为 Beast 的 DynamicBody req.body()
- 为什么 nlohmann/json 序列化 "null" 而不是在 double 上"0"?
- 如何反序列化数组?
- 如何使用提升序列化?
- 序列化多晶型接口
- FlatBuffers/Protobuf 中是否有支持任意 24 位有符号整数定义的可移植二进制序列化架构?