1/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2// test_diamond.cpp
3
4// (C) Copyright 2002-2009 Vladimir Prus and Robert Ramey.
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 inheritance 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)
18namespace std{
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
33int save_count = 0; // used to detect when base class is saved multiple times
34int load_count = 0; // used to detect when base class is loaded multiple times
35
36class base {
37public:
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
64 bool operator==(const base& another) const
65 {
66 return i == another.i && m == another.m;
67 }
68 // make polymorphic by marking at least one function virtual
69 virtual ~base() {};
70private:
71 int i;
72 std::map<int, std::string> m;
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
77// through a pointer. In this example, that doesn't occur so
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 eliminate redundant save/load operations.
84// (It is conceivable 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)
87BOOST_CLASS_TRACKING(base, track_always)
88
89class derived1 : virtual public base {
90public:
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
108class derived2 : virtual public base {
109public:
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
127class final : public derived1, public derived2 {
128public:
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";
136 ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived1);
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";
144 ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived1);
145 ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(derived2);
146 }
147
148 BOOST_SERIALIZATION_SPLIT_MEMBER()
149};
150
151BOOST_CLASS_EXPORT(final)
152
153int
154test_main( int /* argc */, char* /* argv */[] )
155{
156 const char * testfile = boost::archive::tmpnam(NULL);
157 BOOST_REQUIRE(NULL != testfile);
158
159 const final b(3);
160 {
161 test_ostream ofs(testfile, TEST_STREAM_FLAGS);
162 test_oarchive oa(ofs);
163 oa << boost::serialization::make_nvp(n: "b", v: 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(n: "b2", v&: b2);
171 }
172 BOOST_CHECK(1 == save_count);
173 BOOST_CHECK(1 == load_count);
174 BOOST_CHECK(b2 == b);
175 std::remove(filename: 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 {
186 test_ostream ofs(testfile);
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);
201 delete bp;
202 std::remove(filename: testfile);
203
204 return EXIT_SUCCESS;
205}
206

source code of boost/libs/serialization/test/test_diamond.cpp