1 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
2 | // test_smart_cast.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 | // <gennadiy.rozental@tfn.com> |
9 | |
10 | #include <exception> |
11 | #include <boost/serialization/smart_cast.hpp> |
12 | |
13 | #include "test_tools.hpp" |
14 | #include <boost/noncopyable.hpp> |
15 | |
16 | using namespace boost::serialization; |
17 | |
18 | class Base1 : public boost::noncopyable |
19 | { |
20 | char a; |
21 | }; |
22 | |
23 | class Base2 |
24 | { |
25 | int b; |
26 | }; |
27 | |
28 | #ifdef BOOST_MSVC |
29 | # pragma warning(push) |
30 | # pragma warning(disable : 4511 4512) |
31 | #endif |
32 | |
33 | class Derived : public Base1, public Base2 |
34 | { |
35 | long c; |
36 | }; |
37 | |
38 | #ifdef BOOST_MSVC |
39 | #pragma warning(pop) |
40 | #endif |
41 | |
42 | // if compiler doesn't support TPS, the smart_cast syntax doesn't |
43 | // work for references. One has to use the smart_cast_reference |
44 | // syntax (tested below ) instead. |
45 | |
46 | void test_static_reference_cast_2(){ |
47 | Derived d; |
48 | Base1 & b1 = static_cast<Base1 &>(d); |
49 | Base2 & b2 = static_cast<Base2 &>(d); |
50 | |
51 | Base1 & scb1 = smart_cast<Base1 &, Derived &>(u&: d); |
52 | Base2 & scb2 = smart_cast<Base2 &, Derived &>(u&: d); |
53 | BOOST_CHECK_EQUAL(& b1, & scb1); |
54 | BOOST_CHECK_EQUAL(& b2, & scb2); |
55 | |
56 | // downcast |
57 | // BOOST_CHECK_EQUAL(& d, & (smart_cast<Derived &, Base1 &>(b1))); |
58 | // BOOST_CHECK_EQUAL(& d, & (smart_cast<Derived &, Base2 &>(b2))); |
59 | |
60 | // crosscast pointers fails at compiler time |
61 | // BOOST_CHECK_EQUAL(pB2,smart_cast<B2 *>(pB1)); |
62 | // though explicit cross cast will always work |
63 | BOOST_CHECK_EQUAL(& b2,( |
64 | & smart_cast<Base2 &, Derived &>( |
65 | smart_cast<Derived &, Base1 &>(b1) |
66 | )) |
67 | ); |
68 | } |
69 | |
70 | void test_static_reference_cast_1(){ |
71 | Derived d; |
72 | Base1 & b1 = static_cast<Base1 &>(d); |
73 | Base2 & b2 = static_cast<Base2 &>(d); |
74 | |
75 | Base1 & scb1 = smart_cast_reference<Base1 &>(u&: d); |
76 | Base2 & scb2 = smart_cast_reference<Base2 &>(u&: d); |
77 | BOOST_CHECK_EQUAL(& b1, & scb1); |
78 | BOOST_CHECK_EQUAL(& b2, & scb2); |
79 | |
80 | // downcast |
81 | BOOST_CHECK_EQUAL(& d, & (smart_cast_reference<Derived &>(b1))); |
82 | BOOST_CHECK_EQUAL(& d, & (smart_cast_reference<Derived &>(b2))); |
83 | |
84 | // crosscast pointers fails at compiler time |
85 | // BOOST_CHECK_EQUAL(pB2,smart_cast<B2 *>(pB1)); |
86 | // though explicit cross cast will always work |
87 | BOOST_CHECK_EQUAL(& b2,( |
88 | & smart_cast_reference<Base2 &>( |
89 | smart_cast_reference<Derived &>(b1) |
90 | )) |
91 | ); |
92 | } |
93 | |
94 | void test_static_pointer_cast(){ |
95 | // pointers |
96 | Derived d; |
97 | Derived *pD = & d; |
98 | Base1 *pB1 = pD; |
99 | Base2 *pB2 = pD; |
100 | |
101 | // upcast |
102 | BOOST_CHECK_EQUAL(pB1, smart_cast<Base1 *>(pD)); |
103 | BOOST_CHECK_EQUAL(pB2, smart_cast<Base2 *>(pD)); |
104 | |
105 | // downcast |
106 | BOOST_CHECK_EQUAL(pD, smart_cast<Derived *>(pB1)); |
107 | BOOST_CHECK_EQUAL(pD, smart_cast<Derived *>(pB2)); |
108 | |
109 | // crosscast pointers fails at compiler time |
110 | // BOOST_CHECK_EQUAL(pB2, smart_cast<Base2 *>(pB1)); |
111 | |
112 | // though explicit cross cast will always work |
113 | BOOST_CHECK_EQUAL(pB2, |
114 | smart_cast<Base2 *>( |
115 | smart_cast<Derived *>(pB1) |
116 | ) |
117 | ); |
118 | } |
119 | |
120 | class VBase1 : public boost::noncopyable |
121 | { |
122 | char a; |
123 | public: |
124 | virtual ~VBase1(){}; |
125 | }; |
126 | |
127 | class VBase2 |
128 | { |
129 | int b; |
130 | public: |
131 | virtual ~VBase2(){}; |
132 | }; |
133 | |
134 | #ifdef BOOST_MSVC |
135 | # pragma warning(push) |
136 | # pragma warning(disable : 4511 4512) |
137 | #endif |
138 | |
139 | class VDerived : public VBase1, public VBase2 |
140 | { |
141 | long c; |
142 | public: |
143 | virtual ~VDerived(){}; |
144 | }; |
145 | |
146 | #ifdef BOOST_MSVC |
147 | #pragma warning(pop) |
148 | #endif |
149 | |
150 | // see above |
151 | |
152 | void test_dynamic_reference_cast_2(){ |
153 | VDerived d; |
154 | VBase1 &b1 = dynamic_cast<VBase1 &>(d); |
155 | VBase2 &b2 = static_cast<VBase2 &>(d); |
156 | |
157 | VBase1 & vb1 = smart_cast<VBase1 &, VDerived &>(u&: d); |
158 | BOOST_CHECK_EQUAL(& b1, & vb1); |
159 | BOOST_CHECK_EQUAL(& b2, (& smart_cast<VBase2 &, VDerived &>(d))); |
160 | |
161 | // downcast |
162 | BOOST_CHECK_EQUAL(& d, (& smart_cast<VDerived &, VBase1 &>(b1))); |
163 | BOOST_CHECK_EQUAL(& d, (& smart_cast<VDerived &, VBase2 &>(b2))); |
164 | |
165 | // crosscast |
166 | BOOST_CHECK_EQUAL(& b2, (& smart_cast<VBase2 &, VBase1 &>(b1))); |
167 | |
168 | // explicit cross cast should always work |
169 | BOOST_CHECK_EQUAL(& b2, ( |
170 | & smart_cast<VBase2 &, VDerived &>( |
171 | smart_cast<VDerived &, VBase1 &>(b1) |
172 | )) |
173 | ); |
174 | } |
175 | |
176 | void test_dynamic_reference_cast_1(){ |
177 | VDerived d; |
178 | VBase1 &b1 = dynamic_cast<VBase1 &>(d); |
179 | VBase2 &b2 = static_cast<VBase2 &>(d); |
180 | |
181 | VBase1 & vb1 = smart_cast_reference<VBase1 &>(u&: d); |
182 | BOOST_CHECK_EQUAL(& b1, & vb1); |
183 | BOOST_CHECK_EQUAL(& b2, (& smart_cast_reference<VBase2 &>(d))); |
184 | |
185 | // downcast |
186 | BOOST_CHECK_EQUAL(& d, (& smart_cast_reference<VDerived &>(b1))); |
187 | BOOST_CHECK_EQUAL(& d, (& smart_cast_reference<VDerived &>(b2))); |
188 | |
189 | // crosscast |
190 | BOOST_CHECK_EQUAL(& b2, (& smart_cast_reference<VBase2 &>(b1))); |
191 | |
192 | // explicit cross cast should always work |
193 | BOOST_CHECK_EQUAL(& b2, ( |
194 | & smart_cast_reference<VBase2 &>( |
195 | smart_cast_reference<VDerived &>(b1) |
196 | )) |
197 | ); |
198 | } |
199 | |
200 | void test_dynamic_pointer_cast(){ |
201 | // pointers |
202 | VDerived d; |
203 | VDerived *pD = & d; |
204 | VBase1 *pB1 = pD; |
205 | VBase2 *pB2 = pD; |
206 | |
207 | // upcast |
208 | BOOST_CHECK_EQUAL(pB1, smart_cast<VBase1 *>(pD)); |
209 | BOOST_CHECK_EQUAL(pB2, smart_cast<VBase2 *>(pD)); |
210 | |
211 | // downcast |
212 | BOOST_CHECK_EQUAL(pD, smart_cast<VDerived *>(pB1)); |
213 | BOOST_CHECK_EQUAL(pD, smart_cast<VDerived *>(pB2)); |
214 | |
215 | // crosscast pointers fails at compiler time |
216 | BOOST_CHECK_EQUAL(pB2, smart_cast<VBase2 *>(pB1)); |
217 | // though explicit cross cast will always work |
218 | BOOST_CHECK_EQUAL(pB2, |
219 | smart_cast<VBase2 *>( |
220 | smart_cast<VDerived *>(pB1) |
221 | ) |
222 | ); |
223 | } |
224 | |
225 | int |
226 | test_main(int /* argc */, char * /* argv */[]) |
227 | { |
228 | test_static_reference_cast_2(); |
229 | test_static_reference_cast_1(); |
230 | test_static_pointer_cast(); |
231 | test_dynamic_reference_cast_2(); |
232 | test_dynamic_reference_cast_1(); |
233 | test_dynamic_pointer_cast(); |
234 | |
235 | return EXIT_SUCCESS; |
236 | } |
237 | |