1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // test_void_cast.cpp: test implementation of run-time casting of void pointers
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 <cstddef> // NULL
11 #include "test_tools.hpp"
12 #include <boost/serialization/extended_type_info_typeid.hpp>
13 #include <boost/serialization/void_cast.hpp>
14 #include <boost/serialization/singleton.hpp>
15 
16 class Base1
17 {
18     char a;
19 };
20 
21 class Base2
22 {
23     int b;
24 };
25 
26 class Derived : public Base1, public Base2
27 {
28     long c;
29 };
30 
31 class MostDerived : public Derived
32 {
33     char d[32];
34 };
35 
36 template<class T>
eti()37 const boost::serialization::extended_type_info & eti(){
38     return boost::serialization::singleton<
39         boost::serialization::extended_type_info_typeid< T >
40     >::get_const_instance();
41 }
42 
43 int
test_main(int,char * [])44 test_main( int /* argc */, char* /* argv */[] )
45 {
46     MostDerived md;
47     MostDerived* pmd =& md;
48     Derived* pd = static_cast<Derived*>(pmd);
49 
50     Base2* pb2 = static_cast<Base2*>(pmd);
51     Base1* pb1 = static_cast<Base1*>(pd);
52 
53     void* vpmd = static_cast<void*>(pmd);
54     void* vpb1 = static_cast<void*>(pb1);
55     void* vpb2 = static_cast<void*>(pb2);
56     void* vpd = static_cast<void*>(pd);
57 
58     // simple casts only requiring table lookup
59     BOOST_CHECK(vpd == boost::serialization::void_downcast(
60         eti<Derived>(),
61         eti<Base1>(),
62         vpb1
63     ));
64     BOOST_CHECK(vpb1 == boost::serialization::void_upcast(
65         eti<Derived>(),
66         eti<Base1>(),
67         vpd
68     ));
69     BOOST_CHECK(vpd == boost::serialization::void_downcast(
70         eti<Derived>(),
71         eti<Base2>(),
72         vpb2
73     ));
74     BOOST_CHECK(vpb2 == boost::serialization::void_upcast(
75         eti<Derived>(),
76         eti<Base2>(),
77         vpd
78     ));
79     BOOST_CHECK(vpmd == boost::serialization::void_downcast(
80         eti<MostDerived>(),
81         eti<Derived>(),
82         vpd
83     ));
84     BOOST_CHECK(vpd == boost::serialization::void_upcast(
85         eti<MostDerived>(),
86         eti<Derived>(),
87         vpmd
88     ));
89     // note relationship between MostDerived and Base1 is automatically derived
90     BOOST_CHECK(vpmd == boost::serialization::void_downcast(
91         eti<MostDerived>(),
92         eti<Base1>(),
93         vpb1
94     ));
95     BOOST_CHECK(vpb1 == boost::serialization::void_upcast(
96         eti<MostDerived>(),
97         eti<Base1>(),
98         vpmd
99     ));
100 
101     // note relationship between MostDerived and Base2 is automatically derived
102     BOOST_CHECK(vpmd == boost::serialization::void_downcast(
103         eti<MostDerived>(),
104         eti<Base2>(),
105         vpb2
106     ));
107     BOOST_CHECK(vpb2 == boost::serialization::void_upcast(
108         eti<MostDerived>(),
109         eti<Base2>(),
110         vpmd
111     ));
112 
113     // note: currently derivations are not optimised.  See void_cast.cpp
114     // for and explanation.  These should still work though.
115 
116     // need to double check to validate speed up optimization of derivations
117     BOOST_CHECK(vpmd == boost::serialization::void_downcast(
118         eti<MostDerived>(),
119         eti<Base1>(),
120         vpb1
121     ));
122     BOOST_CHECK(vpb1 == boost::serialization::void_upcast(
123         eti<MostDerived>(),
124         eti<Base1>(),
125         vpmd
126     ));
127     BOOST_CHECK(vpmd == boost::serialization::void_downcast(
128         eti<MostDerived>(),
129         eti<Base2>(),
130         vpb2
131     ));
132     BOOST_CHECK(vpb2 == boost::serialization::void_upcast(
133         eti<MostDerived>(),
134         eti<Base2>(),
135         vpmd
136     ));
137 
138     // check things that should fail
139     BOOST_CHECK(NULL == boost::serialization::void_downcast(
140         eti<Base2>(),
141         eti<Base1>(),
142         vpb1
143     ));
144 
145     // note that a fundamental feature is that derived/base pairs are created
146     // at compiler time so that all are registered before the main program starts
147     // so leave the registration here at the end to verify this. Note bogus arguments
148     // to workaround msvc 6 bug
149     boost::serialization::void_cast_register<Derived, Base1>(
150         static_cast<Derived *>(NULL),
151         static_cast<Base1 *>(NULL)
152     );
153     boost::serialization::void_cast_register<Derived, Base2>(
154         static_cast<Derived *>(NULL),
155         static_cast<Base2 *>(NULL)
156     );
157     boost::serialization::void_cast_register<MostDerived, Derived>(
158         static_cast<MostDerived *>(NULL),
159         static_cast<Derived *>(NULL)
160     );
161 
162     return EXIT_SUCCESS;
163 }
164 
165 // EOF
166