1 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
2 | // test_non_default_ctor.cpp |
3 | |
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) |
8 | |
9 | // should pass compilation and execution |
10 | |
11 | // this tests: |
12 | // a) non-intrusive method of implementing serialization |
13 | // b) usage of a non-default constructor |
14 | |
15 | #include <cstddef> // NULL |
16 | #include <cstdio> // remove() |
17 | #include <fstream> |
18 | #include <cstdlib> // for rand() |
19 | #include <boost/config.hpp> |
20 | #include <boost/detail/workaround.hpp> |
21 | #include <boost/limits.hpp> |
22 | #if BOOST_CXX_VERSION > 199711L // only include floating point if C++ version >= C++11 |
23 | #include <boost/math/special_functions/next.hpp> |
24 | #endif |
25 | #if defined(BOOST_NO_STDC_NAMESPACE) |
26 | namespace std{ |
27 | using ::rand; |
28 | using ::remove; |
29 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) |
30 | using ::numeric_limits; |
31 | #endif |
32 | } |
33 | #endif |
34 | |
35 | #include <boost/archive/archive_exception.hpp> |
36 | #include "test_tools.hpp" |
37 | |
38 | /////////////////////////////////////////////////////// |
39 | // simple class test - using non-intrusive syntax |
40 | // illustrates the usage of the non-intrusive syntax |
41 | class A |
42 | { |
43 | friend class boost::serialization::access; |
44 | |
45 | // note const values can only be initialized with a non |
46 | // non-default constructor |
47 | const int i; |
48 | |
49 | signed char s; |
50 | unsigned char t; |
51 | signed int u; |
52 | unsigned int v; |
53 | float w; |
54 | double x; |
55 | bool operator==(const A & rhs) const; |
56 | bool operator<(const A & rhs) const; |
57 | |
58 | template<class Archive> |
59 | void serialize(Archive & ar,const unsigned int /* file_version */){ |
60 | ar & BOOST_SERIALIZATION_NVP(s); |
61 | ar & BOOST_SERIALIZATION_NVP(t); |
62 | ar & BOOST_SERIALIZATION_NVP(u); |
63 | ar & BOOST_SERIALIZATION_NVP(v); |
64 | ar & BOOST_SERIALIZATION_NVP(w); |
65 | ar & BOOST_SERIALIZATION_NVP(x); |
66 | } |
67 | A(const A & rhs); |
68 | A & operator=(const A & rhs); |
69 | public: |
70 | static int count; |
71 | const int & get_i() const { |
72 | return i; |
73 | } |
74 | A(int i_); |
75 | ~A(); |
76 | }; |
77 | |
78 | int A::count = 0; |
79 | |
80 | A::A(int i_) : |
81 | i(i_), |
82 | s(static_cast<signed char>(0xff & std::rand())), |
83 | t(static_cast<signed char>(0xff & std::rand())), |
84 | u(std::rand()), |
85 | v(std::rand()), |
86 | w((float)std::rand() / std::rand()), |
87 | x((double)std::rand() / std::rand()) |
88 | { |
89 | ++count; |
90 | } |
91 | |
92 | A::~A(){ |
93 | --count; |
94 | } |
95 | |
96 | bool A::operator==(const A &rhs) const |
97 | { |
98 | return |
99 | s == rhs.s |
100 | && t == rhs.t |
101 | && u == rhs.u |
102 | && v == rhs.v |
103 | #if BOOST_CXX_VERSION > 199711L // only include floating point if C++ version >= C++11 |
104 | && std::abs( x: boost::math::float_distance(a: w, b: rhs.w)) < 2 |
105 | && std::abs( x: boost::math::float_distance(a: x, b: rhs.x)) < 2 |
106 | #endif |
107 | ; |
108 | } |
109 | |
110 | bool A::operator<(const A &rhs) const |
111 | { |
112 | if(! (s == rhs.s) ) |
113 | return s < rhs.s; |
114 | if(! (t == rhs.t) ) |
115 | return t < rhs.t; |
116 | if(! (u == rhs.u) ) |
117 | return t < rhs.u; |
118 | if(! (v == rhs.v) ) |
119 | return t < rhs.v; |
120 | #if BOOST_CXX_VERSION > 199711L // only include floating point if C++ version >= C++11 |
121 | if(std::abs( x: boost::math::float_distance(a: w, b: rhs.w)) > 1) |
122 | return false; |
123 | if(std::abs( x: boost::math::float_distance(a: x, b: rhs.x)) > 1) |
124 | return false; |
125 | #endif |
126 | return false; |
127 | } |
128 | |
129 | namespace boost { |
130 | namespace serialization { |
131 | |
132 | template<class Archive> |
133 | inline void save_construct_data( |
134 | Archive & ar, |
135 | const A * a, |
136 | const unsigned int /* file_version */ |
137 | ){ |
138 | // variable used for construction |
139 | ar << boost::serialization::make_nvp(n: "i" , v: a->get_i()); |
140 | } |
141 | |
142 | template<class Archive> |
143 | inline void load_construct_data( |
144 | Archive & ar, |
145 | A * a, |
146 | const unsigned int /* file_version */ |
147 | ){ |
148 | int i; |
149 | ar >> boost::serialization::make_nvp(n: "i" , v&: i); |
150 | ::new(a)A(i); |
151 | } |
152 | |
153 | } // serialization |
154 | } // namespace boost |
155 | |
156 | void save(const char * testfile){ |
157 | test_ostream os(testfile, TEST_STREAM_FLAGS); |
158 | test_oarchive oa(os, TEST_ARCHIVE_FLAGS); |
159 | A a(2); |
160 | |
161 | oa << BOOST_SERIALIZATION_NVP(a); |
162 | |
163 | // save a copy pointer to this item |
164 | A *pa1 = &a; |
165 | oa << BOOST_SERIALIZATION_NVP(pa1); |
166 | |
167 | // save pointer to a new object |
168 | A *pa2 = new A(4); |
169 | oa << BOOST_SERIALIZATION_NVP(pa2); |
170 | |
171 | delete pa2; |
172 | } |
173 | void load(const char * testfile){ |
174 | test_istream is(testfile, TEST_STREAM_FLAGS); |
175 | test_iarchive ia(is, TEST_ARCHIVE_FLAGS); |
176 | |
177 | A a(4); |
178 | ia >> BOOST_SERIALIZATION_NVP(a); |
179 | |
180 | A *pa1; |
181 | ia >> BOOST_SERIALIZATION_NVP(pa1); |
182 | BOOST_CHECK_MESSAGE(pa1 == &a, "Copy of pointer not correctly restored" ); |
183 | |
184 | A *pa2; |
185 | ia >> BOOST_SERIALIZATION_NVP(pa2); |
186 | BOOST_CHECK_MESSAGE(pa2 != &a, "Pointer not correctly restored" ); |
187 | |
188 | delete pa2; |
189 | } |
190 | |
191 | int |
192 | test_main( int /* argc */, char* /* argv */[] ) |
193 | { |
194 | const char * testfile = boost::archive::tmpnam(NULL); |
195 | BOOST_REQUIRE(NULL != testfile); |
196 | save(testfile); |
197 | load(testfile); |
198 | BOOST_CHECK(0 == A::count); |
199 | std::remove(filename: testfile); |
200 | return EXIT_SUCCESS; |
201 | } |
202 | |
203 | // EOF |
204 | |