[boost.Serialization V1.42.0] Question about BOOST_SERIALIZATION_SPLIT_FREE and non-public members

Hello, I'm trying to add Boost serialization to a class which has private data members. I'm using the "non-intrusive" free save/load split method. I've added "friend class boost::serialization::access;" to my class, but I still receive a "cannot access private member..." compiler error. How can I give the load/save functions friend access to my class? I'm using Visual Studio 2008 with Boost Version 1.42.0. Thanks, Glen

I'm afraid declaring boost::serialization::access a friend is only helpful if you choose the intrusive approach and your serialize member function is not public. If you need the members to be non-public and a "non-intrusive" approach, it seems you have to use a workaround like a derived "accessor class" that exposes the private members. See http://stackoverflow.com/questions/1687579/boost-serialization-access-to-pro... for an example. Have a nice day, Stefan

On Thu, Aug 5, 2010 at 8:03 PM, Stefan van Kessel <van_kessel@freenet.de>wrote:
I'm afraid declaring boost::serialization::access a friend is only helpful if you choose the intrusive approach and your serialize member function is not public. If you need the members to be non-public and a "non-intrusive" approach, it seems you have to use a workaround like a derived "accessor class" that exposes the private members. See http://stackoverflow.com/questions/1687579/boost-serialization-access-to-pro... an example.
Have a nice day, Stefan
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Stefan, Thanks for the response. Unfortunately, I think the workaround from stackoverflow would only allow me to access protected members -- not private ones. I did come up with another option that seems to be working for me. I created a save_handler(xml_oarchive& oa, const CMyObject& rObj, const unsigned int version) and load_handler(xml_iarchive& ia, CMyObject& rObj, const unsigned int version) function. I gave these two functions friend access to my class being serialized so they have access to the private members. I have the split/free functions, boost::serialization::save() and boost::serialization::load(), call my handler functions to do the actual serialization. Glen

gmkdroid wrote:
Hello,
I'm trying to add Boost serialization to a class which has private data members. I'm using the "non-intrusive" free save/load split method. I've added "friend class boost::serialization::access;" to my class, but I still receive a "cannot access private member..." compiler error. How can I give the load/save functions friend access to my class?
I'm not aware of any problem in this area. If you want to make a small example, we'll take a look at it. Robert Ramey
I'm using Visual Studio 2008 with Boost Version 1.42.0.
Thanks,
Glen _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Fri, Aug 6, 2010 at 6:40 PM, Robert Ramey <ramey@rrsd.com> wrote:
gmkdroid wrote:
Hello,
I'm trying to add Boost serialization to a class which has private data members. I'm using the "non-intrusive" free save/load split method. I've added "friend class boost::serialization::access;" to my class, but I still receive a "cannot access private member..." compiler error. How can I give the load/save functions friend access to my class?
I'm not aware of any problem in this area. If you want to make a small example, we'll take a look at it.
Robert,
Here's an example of the issue I'm having: *MyObject.h* ////////////////////////////////////////////////////////////////////////////////////// #include <boost/serialization/access.hpp> class CMyObject { public: friend class boost::serialization::access; CMyObject(void) : m_nPrivateData(123) { } ~CMyObject(void) { } private: int m_nPrivateData; }; *Serializer_MyObject.h* ////////////////////////////////////////////////////////////////////////////////////// #include "MyObject.h" #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <boost/serialization/split_free.hpp> BOOST_SERIALIZATION_SPLIT_FREE(CMyObject) namespace boost { namespace serialization { template<class Archive> void save(Archive & ar, const CMyObject& t, unsigned int version) { ar << boost::serialization::make_nvp("CMyObject", t.m_nPrivateData); } template<class Archive> void load(Archive & ar, CMyObject& t, unsigned int version) { ar >> boost::serialization::make_nvp("CMyObject", t.m_nPrivateData); } }} // boost and serialization namespaces The program compiles fine if m_nPrivateData is made public, but fails if its private. Is there something else I should be using instead of boost::serialization::access? Thanks, Glen _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Mon, Aug 9, 2010 at 7:43 PM, gmkdroid <gmkdroid@gmail.com> wrote:
Here's an example of the issue I'm having:
*MyObject.h*
////////////////////////////////////////////////////////////////////////////////////// #include <boost/serialization/access.hpp> class CMyObject { public: friend class boost::serialization::access; CMyObject(void) : m_nPrivateData(123) { } ~CMyObject(void) { } private: int m_nPrivateData; };
Your friend class boost::serialization::access; is in the public section, put it in the private section then it can access the private data.

AMDG OvermindDL1 wrote:
On Mon, Aug 9, 2010 at 7:43 PM, gmkdroid <gmkdroid@gmail.com> wrote:
Here's an example of the issue I'm having:
*MyObject.h*
////////////////////////////////////////////////////////////////////////////////////// #include <boost/serialization/access.hpp> class CMyObject { public: friend class boost::serialization::access; CMyObject(void) : m_nPrivateData(123) { } ~CMyObject(void) { } private: int m_nPrivateData; };
Your friend class boost::serialization::access; is in the public section, put it in the private section then it can access the private data.
public vs. private doesn't affect friend declarations. In Christ, Steven Watanabe

gmkdroid wrote:
On Fri, Aug 6, 2010 at 6:40 PM, Robert Ramey <ramey@rrsd.com> wrote:
gmkdroid wrote:
I just compiled the code below - with my msvc 7.1 compiler without problem. What compiler are you using? Robert Ramey ////////////////////////////////////////////////////////////////////////////////////// #include <boost/serialization/access.hpp> class CMyObject { public: friend class boost::serialization::access; CMyObject(void) : m_nPrivateData(123) { } ~CMyObject(void) { } private: int m_nPrivateData; }; ////////////////////////////////////////////////////////////////////////////////////// #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <boost/serialization/split_free.hpp> BOOST_SERIALIZATION_SPLIT_FREE(CMyObject) namespace boost { namespace serialization { template<class Archive> void save(Archive & ar, const CMyObject& t, unsigned int version) { ar << boost::serialization::make_nvp("CMyObject", t.m_nPrivateData); } template<class Archive> void load(Archive & ar, CMyObject& t, unsigned int version) { ar >> boost::serialization::make_nvp("CMyObject", t.m_nPrivateData); } }} // boost and serialization namespaces

Robert Ramey wrote:
gmkdroid wrote:
On Fri, Aug 6, 2010 at 6:40 PM, Robert Ramey <ramey@rrsd.com> wrote:
gmkdroid wrote:
I just compiled the code below - with my msvc 7.1 compiler without problem. What compiler are you using?
Robert Ramey
////////////////////////////////////////////////////////////////////////////////////// #include <boost/serialization/access.hpp> class CMyObject { public: friend class boost::serialization::access; CMyObject(void) : m_nPrivateData(123) { } ~CMyObject(void) { } private: int m_nPrivateData; };
////////////////////////////////////////////////////////////////////////////////////// #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <boost/serialization/split_free.hpp>
BOOST_SERIALIZATION_SPLIT_FREE(CMyObject)
namespace boost { namespace serialization { template<class Archive> void save(Archive & ar, const CMyObject& t, unsigned int version) { ar << boost::serialization::make_nvp("CMyObject", t.m_nPrivateData); }
template<class Archive> void load(Archive & ar, CMyObject& t, unsigned int version) { ar >> boost::serialization::make_nvp("CMyObject", t.m_nPrivateData); }
}} // boost and serialization namespaces
whoops, spoke too soon, I added the following to make sure things were instantiated. #include <fstream> int main(int argc, char *argv[]){ std::ifstream is; boost::archive::xml_iarchive ia(is); CMyObject obj; ia >> BOOST_SERIALIZATION_NVP(obj); } and I got your error. I'll look at it Robert Ramey

I looked into this a little bit. First I can see the the friend ...access will only work for intrusive serialization. But I can see that it's straight forward to just make the free save/load functions friend templates - EXCEPT that not all compilers do this. Sooo here is what I had to do to sneak it past my msvc 7.1 compiler. Robert Ramey ////////////////////////////////////////////////////////////////////////////////////// #include <boost/config.hpp> #include <boost/serialization/split_free.hpp> class CMyObject { #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: friend template<class Archive> void save(Archive & ar, const CMyObject& t, unsigned int version); friend template<class Archive> void load(Archive & ar, CMyObject& t, unsigned int version); #else public: #endif int m_nPrivateData; public: CMyObject(void) : m_nPrivateData(123) { } ~CMyObject(void) { } }; BOOST_SERIALIZATION_SPLIT_FREE(CMyObject) ////////////////////////////////////////////////////////////////////////////////////// #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> namespace boost { namespace serialization { template<class Archive> void save(Archive & ar, const CMyObject& t, unsigned int version) { ar << boost::serialization::make_nvp("CMyObject", t.m_nPrivateData); } template<class Archive> void load(Archive & ar, CMyObject& t, unsigned int version) { ar >> boost::serialization::make_nvp("CMyObject", t.m_nPrivateData); } }} // boost and serialization namespaces #include <fstream> int main(int argc, char *argv[]){ std::ifstream is; boost::archive::xml_iarchive ia(is); CMyObject obj; ia >> BOOST_SERIALIZATION_NVP(obj); }

On Tue, Aug 10, 2010 at 3:30 AM, Robert Ramey <ramey@rrsd.com> wrote:
I looked into this a little bit.
First I can see the the friend ...access will only work for intrusive serialization.
But I can see that it's straight forward to just make the free save/load functions friend templates - EXCEPT that not all compilers do this.
Robert, I tried your suggestion, but VS2008 didn't compile. I made a few minor tweaks and its working now. Here's what I ended up using: *MyObject.h* ////////////////////////////////////////////////////////////////////////////////////// #pragma once #include "Serializer_MyObject.h" class CMyObject { private: template<class Archive> friend void boost::serialization::save(Archive & ar, const CMyObject& t, unsigned int version); template<class Archive> friend void boost::serialization::load(Archive & ar, CMyObject& t, unsigned int version); int m_nPrivateData; public: CMyObject(void) : m_nPrivateData(123) { } ~CMyObject(void) { } }; *Serializer_MyObject.h* ////////////////////////////////////////////////////////////////////////////////////// #pragma once #include <boost/config.hpp> #include <boost/serialization/split_free.hpp> #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> class CMyObject; BOOST_SERIALIZATION_SPLIT_FREE(CMyObject) namespace boost { namespace serialization { template<class Archive> void save(Archive & ar, const CMyObject& t, unsigned int version) { ar << boost::serialization::make_nvp("CMyObject", t.m_nPrivateData); } template<class Archive> void load(Archive & ar, CMyObject& t, unsigned int version) { ar >> boost::serialization::make_nvp("CMyObject", t.m_nPrivateData); } }} // end boost::serialization namespaces ** ** *main.cpp* ////////////////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include <fstream> #include <iostream> #include "MyObject.h" int _tmain(int argc, _TCHAR* argv[]) { std::ofstream ofs("C:\\test.xml"); boost::archive::xml_oarchive oa(ofs); CMyObject obj; oa << BOOST_SERIALIZATION_NVP(obj); ofs.close(); CMyObject newobj; std::ifstream ifs("C:\\test.xml"); boost::archive::xml_iarchive ia(ifs); ia >> BOOST_SERIALIZATION_NVP(newobj);; ifs.close(); } Thanks for your help. Glen
participants (5)
-
gmkdroid
-
OvermindDL1
-
Robert Ramey
-
Stefan van Kessel
-
Steven Watanabe