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