获取非侵入式提升序列化 C++ 的私有数据成员
Get private data members for non intrusive boost serialization C++
我已经尝试为我的非成员 serialize()
函数提供 class 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);
不幸的是,当我尝试使用 GetRef()
或 GetId()
.
时,执行一直告诉我 uncaught exception of type boost::archive::xml_archive_exception - Invalid XML tag name
如果我在 public.
时直接访问 m_id
,效果会很好
有什么好的方法吗?
你可以用的好 old-fashioned 朋友:
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元素名
Sadly, having the reference getter break encapsulation in a horrific way. I'd personally prefer to have m_id
public in the first place, instead.
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()
方法更具侵入性。现在,您可以在 class:
中隐藏私有访问权限
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);
}
}
}
当然你仍然需要实现它,但这可以在单独的 header 中完成并且根本不会影响 class 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);
}
};
仅供补充信息:为了从 sehe 获得第一个解决方案:
你需要一个前向减速的朋友方法如下:
// 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();
};
我花了一些时间才开始工作。
干杯
sehe第一个解的补充信息:
该解决方案需要 two-phase 查找和/或参数依赖查找。不幸的是,MSVC 还没有完全支持它。
在带有 boost 1.70 的 VS Community 2019 16.1.6 中编译它会导致一个模糊的错误:
Error C2063 'boost::serialization::serialize': not a function
尽管通过 /permissive- 标志启用了一致性模式并且选择了最新的语言标准 /std::c++latest,如 this MSVC Blog Post 中所述。
在友元声明中添加类型名限定符解决问题:
template <typename Ar, typename U> friend void boost::serialization::serialize(typename Ar&, A<U>&, const unsigned);
更有趣令人沮丧:
如果class A 不是模板化的class,那么无论哪种方式都不起作用,与上述相同的错误...
示例代码:http://coliru.stacked-crooked.com/a/ecfbb39d5975d753
我已经尝试为我的非成员 serialize()
函数提供 class 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);
不幸的是,当我尝试使用 GetRef()
或 GetId()
.
时,执行一直告诉我 uncaught exception of type boost::archive::xml_archive_exception - Invalid XML tag name
如果我在 public.
m_id
,效果会很好
有什么好的方法吗?
你可以用的好 old-fashioned 朋友:
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元素名
Sadly, having the reference getter break encapsulation in a horrific way. I'd personally prefer to have
m_id
public in the first place, instead.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()
方法更具侵入性。现在,您可以在 class: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); } } }
当然你仍然需要实现它,但这可以在单独的 header 中完成并且根本不会影响 class 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); } };
仅供补充信息:为了从 sehe 获得第一个解决方案:
你需要一个前向减速的朋友方法如下:
// 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();
};
我花了一些时间才开始工作。
干杯
sehe第一个解的补充信息:
该解决方案需要 two-phase 查找和/或参数依赖查找。不幸的是,MSVC 还没有完全支持它。
在带有 boost 1.70 的 VS Community 2019 16.1.6 中编译它会导致一个模糊的错误:
Error C2063 'boost::serialization::serialize': not a function
尽管通过 /permissive- 标志启用了一致性模式并且选择了最新的语言标准 /std::c++latest,如 this MSVC Blog Post 中所述。
在友元声明中添加类型名限定符解决问题:
template <typename Ar, typename U> friend void boost::serialization::serialize(typename Ar&, A<U>&, const unsigned);
更有趣令人沮丧:
如果class A 不是模板化的class,那么无论哪种方式都不起作用,与上述相同的错误... 示例代码:http://coliru.stacked-crooked.com/a/ecfbb39d5975d753