我尝试为我的非成员LD_PRELOAD
函数提供类A
的getter,因为从成员访问是私有的。
serialize()
不幸的是,当我尝试使用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);
或uncaught exception of type boost::archive::xml_archive_exception - Invalid XML tag name
的getter时,执行会一直告诉我GetRef()
。
如果我公开时直接访问GetId()
,它的效果很好。
有没有很好的方法呢?
答案 0 :(得分:12)
你可以使用优秀的老朋友:
<强> Live On 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
。
<强> Live On 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类&lt;&gt; (或其任何专业):
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);
}
};
同时查看 Live On Coliru
答案 1 :(得分:1)
仅供参考:为了获得 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();
};
让我花一点时间让它发挥作用。
干杯
答案 2 :(得分:0)
sehe第一个解决方案的补充信息:
该解决方案需要两阶段查找和/或与参数相关的查找。不幸的是,MSVC尚未完全支持这一点。
在VS Community 2019 16.1.6中以1.70进行编译会导致模糊的错误:
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);
更令人沮丧的 :
如果类A不是模板化类,则无论哪种方式都不会起作用,与上述错误相同... 示例代码:http://coliru.stacked-crooked.com/a/ecfbb39d5975d753