]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
2 | // test_diamond.cpp | |
3 | ||
f67539c2 | 4 | // (C) Copyright 2002-2009 Vladimir Prus and Robert Ramey. |
7c673cae FG |
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) | |
8 | ||
9 | // test of serialization library for diamond inheritence situations | |
10 | ||
11 | #include <cstddef> // NULL | |
12 | #include <fstream> | |
13 | #include <iostream> | |
14 | ||
15 | #include <boost/config.hpp> | |
16 | #include <cstdio> // remove | |
17 | #if defined(BOOST_NO_STDC_NAMESPACE) | |
f67539c2 | 18 | namespace std{ |
7c673cae FG |
19 | using ::remove; |
20 | } | |
21 | #endif | |
22 | ||
23 | #include "test_tools.hpp" | |
24 | ||
25 | #include <boost/serialization/map.hpp> | |
26 | #include <boost/serialization/utility.hpp> | |
27 | #include <boost/serialization/split_member.hpp> | |
28 | #include <boost/serialization/tracking.hpp> | |
29 | #include <boost/serialization/base_object.hpp> | |
30 | #include <boost/serialization/nvp.hpp> | |
31 | #include <boost/serialization/export.hpp> | |
32 | ||
33 | int save_count = 0; // used to detect when base class is saved multiple times | |
34 | int load_count = 0; // used to detect when base class is loaded multiple times | |
35 | ||
36 | class base { | |
37 | public: | |
38 | base() : i(0) {} | |
39 | base(int i) : i(i) | |
40 | { | |
41 | m[i] = "text"; | |
42 | } | |
43 | ||
44 | template<class Archive> | |
45 | void save(Archive &ar, const unsigned int /* file_version */) const | |
46 | { | |
47 | std::cout << "Saving base\n"; | |
48 | ar << BOOST_SERIALIZATION_NVP(i); | |
49 | ar << BOOST_SERIALIZATION_NVP(m); | |
50 | ++save_count; | |
51 | } | |
52 | ||
53 | template<class Archive> | |
54 | void load(Archive & ar, const unsigned int /* file_version */) | |
55 | { | |
56 | std::cout << "Restoring base\n"; | |
57 | ar >> BOOST_SERIALIZATION_NVP(i); | |
58 | ar >> BOOST_SERIALIZATION_NVP(m); | |
59 | ++load_count; | |
60 | } | |
61 | ||
62 | BOOST_SERIALIZATION_SPLIT_MEMBER() | |
63 | ||
f67539c2 | 64 | bool operator==(const base& another) const |
7c673cae FG |
65 | { |
66 | return i == another.i && m == another.m; | |
67 | } | |
68 | // make polymorphic by marking at least one function virtual | |
69 | virtual ~base() {}; | |
70 | private: | |
71 | int i; | |
f67539c2 | 72 | std::map<int, std::string> m; |
7c673cae FG |
73 | }; |
74 | ||
75 | // note: the default is for object tracking to be performed if and only | |
76 | // if and object of the corresponding class is anywhere serialized | |
f67539c2 | 77 | // through a pointer. In this example, that doesn't occur so |
7c673cae FG |
78 | // by default, the shared base object wouldn't normally be tracked. |
79 | // This would leave to multiple save/load operation of the data in | |
80 | // this shared base class. This wouldn't cause an error, but it would | |
81 | // be a waste of time. So set the tracking behavior trait of the base | |
82 | // class to always track serialized objects of that class. This permits | |
83 | // the system to detect and elminate redundent save/load operations. | |
84 | // (It is concievable that this might someday be detected automatically | |
85 | // but for now, this is not done so we have to rely on the programmer | |
86 | // to specify this trait) | |
87 | BOOST_CLASS_TRACKING(base, track_always) | |
88 | ||
89 | class derived1 : virtual public base { | |
90 | public: | |
91 | template<class Archive> | |
92 | void save(Archive &ar, const unsigned int /* file_version */) const | |
93 | { | |
94 | std::cout << "Saving derived1\n"; | |
95 | ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(base); | |
96 | } | |
97 | ||
98 | template<class Archive> | |
99 | void load(Archive & ar, const unsigned int /* file_version */) | |
100 | { | |
101 | std::cout << "Restoring derived1\n"; | |
102 | ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(base); | |
103 | } | |
104 | ||
105 | BOOST_SERIALIZATION_SPLIT_MEMBER() | |
106 | }; | |
107 | ||
108 | class derived2 : virtual public base { | |
f67539c2 | 109 | public: |
7c673cae FG |
110 | template<class Archive> |
111 | void save(Archive &ar, const unsigned int /* file_version */) const | |
112 | { | |
113 | std::cout << "Saving derived2\n"; | |
114 | ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(base); | |
115 | } | |
116 | ||
117 | template<class Archive> | |
118 | void load(Archive & ar, const unsigned int /* file_version */) | |
119 | { | |
120 | std::cout << "Restoring derived2\n"; | |
121 | ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(base); | |
122 | } | |
123 | ||
124 | BOOST_SERIALIZATION_SPLIT_MEMBER() | |
125 | }; | |
126 | ||
127 | class final : public derived1, public derived2 { | |
128 | public: | |
129 | final() {} | |
130 | final(int i) : base(i) {} | |
131 | ||
132 | template<class Archive> | |
133 | void save(Archive &ar, const unsigned int /* file_version */) const | |
134 | { | |
135 | std::cout << "Saving final\n"; | |
f67539c2 | 136 | ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived1); |
7c673cae FG |
137 | ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived2); |
138 | } | |
139 | ||
140 | template<class Archive> | |
141 | void load(Archive & ar, const unsigned int /* file_version */) | |
142 | { | |
143 | std::cout << "Restoring final\n"; | |
f67539c2 | 144 | ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived1); |
7c673cae FG |
145 | ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived2); |
146 | } | |
147 | ||
148 | BOOST_SERIALIZATION_SPLIT_MEMBER() | |
149 | }; | |
150 | ||
151 | BOOST_CLASS_EXPORT(final) | |
152 | ||
153 | int | |
154 | test_main( int /* argc */, char* /* argv */[] ) | |
155 | { | |
156 | const char * testfile = boost::archive::tmpnam(NULL); | |
157 | BOOST_REQUIRE(NULL != testfile); | |
f67539c2 TL |
158 | |
159 | const final b(3); | |
7c673cae FG |
160 | { |
161 | test_ostream ofs(testfile, TEST_STREAM_FLAGS); | |
162 | test_oarchive oa(ofs); | |
163 | oa << boost::serialization::make_nvp("b", b); | |
164 | } | |
165 | ||
166 | final b2; | |
167 | { | |
168 | test_istream ifs(testfile, TEST_STREAM_FLAGS); | |
169 | test_iarchive ia(ifs); | |
170 | ia >> boost::serialization::make_nvp("b2", b2); | |
171 | } | |
172 | BOOST_CHECK(1 == save_count); | |
173 | BOOST_CHECK(1 == load_count); | |
174 | BOOST_CHECK(b2 == b); | |
175 | std::remove(testfile); | |
176 | ||
177 | // do the same test with pointers | |
178 | testfile = boost::archive::tmpnam(NULL); | |
179 | BOOST_REQUIRE(NULL != testfile); | |
180 | ||
181 | save_count = 0; | |
182 | load_count = 0; | |
183 | ||
184 | const base* bp = new final( 3 ); | |
185 | { | |
f67539c2 | 186 | test_ostream ofs(testfile); |
7c673cae FG |
187 | test_oarchive oa(ofs); |
188 | oa << BOOST_SERIALIZATION_NVP(bp); | |
189 | } | |
190 | ||
191 | base* bp2; | |
192 | { | |
193 | test_istream ifs(testfile); | |
194 | test_iarchive ia(ifs); | |
195 | ia >> BOOST_SERIALIZATION_NVP(bp2); | |
196 | } | |
197 | ||
198 | BOOST_CHECK(1 == save_count); | |
199 | BOOST_CHECK(1 == load_count); | |
200 | BOOST_CHECK(*bp2 == *bp); | |
b32b8144 | 201 | delete bp; |
7c673cae FG |
202 | std::remove(testfile); |
203 | ||
204 | return EXIT_SUCCESS; | |
205 | } |