1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // test_enable_shared_from_this.cpp
4 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
5 // Use, modification and distribution is subject to the Boost Software
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // This demonstrates a problem with boost::serialization and boost::enable_shared_from_this.
10 // (boost version 1.53)
11 // See boost TRAC ticket #9567
13 // Given the following class structure:
14 // Base is a simple class
15 // Derived inherits from Base
16 // Derived also inherits from boost::enable_shared_from_this<Derived>
17 // Base and Derived implement boost::serialization
19 // When deserializing an instance of Derived into a vector of boost::shared_ptr<Derived>:
20 // Base and Derived members are reconstructed correctly.
21 // Derived::shared_from_this() works as expected.
23 // But when deserializing an instance of Derived into a vector of boost::shared_ptr<Base>:
24 // Base and Derived members are still reconstructed correctly.
25 // Derived::shared_from_this() throws a bad_weak_ptr exception.
26 // This is because enable_shared_from_this::weak_ptr is NOT reconstructed - It is zero.
30 #include <boost/archive/text_oarchive.hpp>
31 #include <boost/archive/text_iarchive.hpp>
33 #include <boost/enable_shared_from_this.hpp>
34 #include <boost/serialization/shared_ptr.hpp>
35 #include <boost/serialization/export.hpp>
36 #include <boost/serialization/split_free.hpp>
38 #include "test_tools.hpp"
43 namespace serialization
{
45 struct enable_shared_from_this_helper
{
46 std::set
<shared_ptr
<void> > m_esfth
;
47 void record(boost::shared_ptr
<void> sp
){
52 template<class Archive
, class T
>
55 boost::enable_shared_from_this
<T
> & t
,
56 const unsigned int file_version
58 enable_shared_from_this_helper
& h
=
59 ar
.template get_helper
<
60 enable_shared_from_this_helper
63 shared_ptr
<T
> sp
= t
.shared_from_this();
71 friend class boost::serialization::access
;
73 template<class Archive
>
74 void serialize(Archive
& ar
, const unsigned int version
)
76 ar
& BOOST_SERIALIZATION_NVP(m_base
);
80 virtual ~Base() {} // "virtual" forces RTTI, to enable serialization of Derived from Base pointer
85 class Derived
: public Base
, public boost::enable_shared_from_this
<Derived
> {
86 friend class boost::serialization::access
;
88 template<class Archive
>
89 void serialize(Archive
& ar
, const unsigned int version
)
91 ar
& BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base
);
92 ar
& BOOST_SERIALIZATION_BASE_OBJECT_NVP(
93 boost::enable_shared_from_this
<Derived
>
95 ar
& BOOST_SERIALIZATION_NVP(m_derived
);
98 boost::shared_ptr
<Derived
> SharedPtr() { return shared_from_this(); }
103 // The following is required to enable serialization from Base pointer
104 BOOST_CLASS_EXPORT(Derived
)
108 std::stringstream ss
;
110 boost::shared_ptr
<Derived
> d(new Derived());
114 // Get a raw pointer to Derived
115 Derived
* raw_d
= d
.get();
117 // Verify base and derived members
118 BOOST_CHECK(raw_d
->m_base
==1);
119 BOOST_CHECK(raw_d
->m_derived
==2);
121 // verify shared_from_this
122 BOOST_CHECK(d
== raw_d
->SharedPtr());
124 boost::archive::text_oarchive
oa(ss
);
125 oa
& BOOST_SERIALIZATION_NVP(d
);
128 // Deserialize it back into a vector of shared_ptr<Derived>
129 boost::shared_ptr
<Derived
> d
;
131 boost::archive::text_iarchive
ia(ss
);
132 ia
& BOOST_SERIALIZATION_NVP(d
);
134 // Get a raw pointer to Derived
135 Derived
* raw_d
= d
.get();
137 // Verify base and derived members
138 BOOST_CHECK(raw_d
->m_base
==1);
139 BOOST_CHECK(raw_d
->m_derived
==2);
141 // verify shared_from_this
142 BOOST_CHECK(d
== raw_d
->SharedPtr());
148 std::stringstream ss
;
150 boost::shared_ptr
<Base
> b(new Derived());
151 Derived
* raw_d1
= static_cast<Derived
*>(b
.get());
153 raw_d1
->m_derived
= 2;
155 // Get a raw pointer to Derived via shared_ptr<Base>
156 Derived
* raw_d
= static_cast<Derived
*>(b
.get());
158 // Verify base and derived members
159 BOOST_CHECK(raw_d
->m_base
==1);
160 BOOST_CHECK(raw_d
->m_derived
==2);
162 // verify shared_from_this
163 boost::shared_ptr
<Derived
> d
= raw_d
->SharedPtr();
165 // Serialize the vector
166 boost::archive::text_oarchive
oa(ss
);
167 oa
& BOOST_SERIALIZATION_NVP(b
);
170 // Deserialize it back into a vector of shared_ptr<Base>
172 boost::archive::text_iarchive
ia(ss
);
173 boost::shared_ptr
<Base
> b
;
174 ia
& BOOST_SERIALIZATION_NVP(b
);
176 // Get a raw pointer to Derived via shared_ptr<Base>
177 Derived
* raw_d
= static_cast<Derived
*>(b
.get());
178 // Verify base and derived members
179 BOOST_CHECK(raw_d
->m_base
==1);
180 BOOST_CHECK(raw_d
->m_derived
==2);
182 // verify shared_from_this
183 // FAIL: The following line throws bad_weak_ptr exception
184 boost::shared_ptr
<Derived
> d
= raw_d
->SharedPtr();
189 int test_main(int /*argc*/, char * /*argv */[]){