How can boost::serialization be used with std::shared_ptr from C++11?
As of Boost 1.56, the serialization library has built-in support for std::shared_ptr. You do not need to implement your own serialization helper functions if you can use a more recent version of the library.
boost serialize and std::shared_ptr
I suspect you are missing an include,
#include <boost/serialization/shared_ptr.hpp>
link, at the bottom
Also, the example makes it look like aliasing and cycles are taken care of by default.
_Of course, having cycles will lead to potential memory leaks with shared_ptr that have nothing to do with serialization, and you'll still have to heed those (by avoiding cycles or judicious use of weak_ptr)_
See also:
- Template serialization - shared_ptr
- shared_ptrRevisited
C++ shared_ptr serialization
You probably forgot to include
#include <boost/serialization/shared_ptr.hpp>
c++11 shared_ptr + Boost::Serialization
I am not sure if this is the best way to do this but it seems to work.
Changed the namespace and added this load method to shared_ptr specialization header copied from Boost::shared_ptr specialization:
template<class Archive, class T>
inline void load(
Archive & ar,
std::shared_ptr< T > &t,
const unsigned int /* file_version */
){
T * t_ptr;
ar >> boost::serialization::make_nvp("px", t_ptr);
t = std::shared_ptr<T>(t_ptr);
}
How do I make boost::serialization work with std::shared_ptr?
No, std::shared_ptr and boost::shared_ptr are unrelated class templates.
Boost.Serizalization
doesn't support std::shared_ptr
out of the box, but you can add such a support in your application - just take a look at <boost/serialization/shared_ptr.hpp>
header.
How to know if shared_ptr was already serialized to boost archive
The code smell is using a shared_ptr where unique ownership must be guaranteed. What are you going to do when you find a violation? Assert? std::terminate
?
You could make a serialization wrapper that adds the check on de-serialization.
You will depend on library implementation details, because - apparently - while loading there will be a temporary copy of the shared_ptr:
Live On Coliru
#undef NDEBUG
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/wrapper.hpp>
#include <iostream>
template <typename SP> struct Unique {
SP& _ref;
Unique(SP& r):_ref(r){}
template <typename Ar>
void serialize(Ar& ar, unsigned) {
if constexpr (typename Ar::is_saving{}) {
if (_ref && not _ref.unique())
throw std::logic_error("Shared ownership not allowed");
}
ar & _ref;
if constexpr (typename Ar::is_loading{}) {
if (_ref && _ref.use_count() != 2)
throw std::logic_error("Shared ownership not allowed");
}
}
};
template <typename SP>
struct boost::serialization::is_wrapper<Unique<SP>> : boost::mpl::true_ {};
struct Data {
int a,b,c;
void serialize(auto& ar, unsigned) { ar & a & b & c; }
};
static std::string do_write(auto const&... data) {
std::ostringstream oss;
boost::archive::text_oarchive oa(oss);
(oa << ... << data);
return oss.str();
}
static void do_read(std::string const& str, auto&&... data)
{
std::istringstream iss(str);
boost::archive::text_iarchive ia(iss);
(ia >> ... >> data);
}
int main()
{
auto data = std::make_shared<Data>(1, 2, 3);
assert(data.unique());
// okay:
{
auto txt = do_write(data, data, data);
do_read(txt, data);
std::cout << "L:" << __LINE__ << " Success " << std::endl;
}
// still okay:
{
Unique ud{data};
auto txt = do_write(ud);
do_read(txt, ud);
std::cout << "L:" << __LINE__ << " Success " << std::endl;
assert(data.unique());
}
// not okay because not unique:
try
{
auto data_shared(data);
Unique ud{data}, ud_shared{data_shared};
assert(!data.unique());
assert(!data_shared.unique());
auto txt = do_write(ud, ud_shared);
do_read(txt, ud, ud_shared);
std::cout << "L:" << __LINE__ << " Success " << std::endl;
}catch(std::exception const& e) {
std::cout << "L:" << __LINE__ << " Failure " << e.what() << std::endl;
}
}
Prints
L:57 Success
L:65 Success
L:81 Failure Shared ownership not allowed
Summary
Don't do this, because you can't cleanly do it. The alternative is far worse (delving into the object tracking implementation details as some commenters suggested).
Simply
- tighten the type constraints to express your invariant
- perhaps add a validation member to check the invariant
Boost serialization doesn't work with shared_ptr<int>
From the Boost source code around that assertion:
// The most common cause of trapping here would be serializing
// something like shared_ptr<int>. This occurs because int
// is never tracked by default. Wrap int in a trackable type
BOOST_STATIC_ASSERT((tracking_level< T >::value != track_never));
Basically, in order to serialize things like shared_ptr
properly, the pointed-to objects need to be centrally tracked during the serialization process (to identify when multiple pointers point to the same object, so they don't lead to two copies of the object being serialized). Tracking an object is more expensive than not tracking it, though, so primitive types are not tracked (the assumption being that there's gonna be a lot of them). Essentially, this makes it impossible to serialize shared_ptr<primitive_type>
without mucking with the Boost sources. The solution, as the comment says, is to instead serialize some UDT containing an int.
boost serialization std::unique_ptr support
No, there is no out of the box adaption. You will need to provide a non-intrusive adapter yourself. See the tutorial here to get an idea how to do that.
Related Topics
Understanding the Different Clocks of Clock_Gettime()
Switch-Case Statement Without Break
How to Use Lambda Auto Parameters in C++11
Resolving a Circular Dependency Between Template Classes
Compile a Static Binary Which Code There a Function Gethostbyname
Filestorage for Opencv Python API
How to Build a Full Path String (Safely) from Separate Strings
How to Vectorize My Loop with G++
Cmake' Is Not Recognised as an Internal or External Command
How to Overload a Function That Can Tell a Fixed Array from a Pointer
Template Class Member Function Only Specialization
Call of Overloaded Function Is Ambiguous
Creating a New Object from Dynamic Type Info
When Should We Use Sizeof with and Without Parentheses
How Does Q_Foreach (= Foreach) MACro Work and Why Is It That Complex