|
1 #ifndef BOOST_SERIALIZATION_BASE_OBJECT_HPP |
|
2 #define BOOST_SERIALIZATION_BASE_OBJECT_HPP |
|
3 |
|
4 // MS compatible compilers support #pragma once |
|
5 #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|
6 # pragma once |
|
7 #endif |
|
8 |
|
9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
|
10 // base_object.hpp: |
|
11 |
|
12 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . |
|
13 // Use, modification and distribution is subject to the Boost Software |
|
14 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
|
15 // http://www.boost.org/LICENSE_1_0.txt) |
|
16 |
|
17 // See http://www.boost.org for updates, documentation, and revision history. |
|
18 |
|
19 // if no archive headers have been included this is a no op |
|
20 // this is to permit BOOST_EXPORT etc to be included in a |
|
21 // file declaration header |
|
22 |
|
23 #include <boost/config.hpp> |
|
24 #include <boost/detail/workaround.hpp> |
|
25 |
|
26 #include <boost/mpl/eval_if.hpp> |
|
27 #include <boost/mpl/int.hpp> |
|
28 #include <boost/type_traits/is_base_and_derived.hpp> |
|
29 #include <boost/type_traits/is_pointer.hpp> |
|
30 #include <boost/type_traits/is_const.hpp> |
|
31 |
|
32 #include <boost/static_assert.hpp> |
|
33 #include <boost/serialization/type_info_implementation.hpp> |
|
34 #include <boost/serialization/force_include.hpp> |
|
35 #include <boost/serialization/void_cast_fwd.hpp> |
|
36 |
|
37 namespace boost { |
|
38 namespace serialization { |
|
39 |
|
40 namespace detail { |
|
41 // metrowerks CodeWarrior |
|
42 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) |
|
43 // only register void casts if the types are polymorphic |
|
44 template<class Base, class Derived> |
|
45 struct base_register{ |
|
46 struct nothing { |
|
47 static const void_cast_detail::void_caster & invoke(){ |
|
48 return static_cast<const void_cast_detail::void_caster &>( |
|
49 * static_cast<const void_cast_detail::void_caster *>(NULL) |
|
50 ); |
|
51 } |
|
52 }; |
|
53 |
|
54 // hold a reference to the void_cast_register and void_caster in the hope of |
|
55 // ensuring code instantiation for some compilers with over-zealous link time |
|
56 // optimiser. The compiler that demanded this was CW |
|
57 struct reg{ |
|
58 typedef const void_cast_detail::void_caster & (* t_vcr)( |
|
59 const Derived *, |
|
60 const Base * |
|
61 ); |
|
62 t_vcr m_vcr; |
|
63 static const void_cast_detail::void_caster & invoke(){ |
|
64 return void_cast_register<const Derived, const Base>( |
|
65 static_cast<const Derived *>(NULL), |
|
66 static_cast<const Base *>(NULL) |
|
67 ); |
|
68 } |
|
69 reg() : |
|
70 m_vcr(static_cast<t_vcr>(void_cast_register)) |
|
71 { |
|
72 } |
|
73 } m_reg; |
|
74 |
|
75 static const void_cast_detail::void_caster & invoke(){ |
|
76 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< |
|
77 BOOST_DEDUCED_TYPENAME type_info_implementation<Base>::type::is_polymorphic, |
|
78 mpl::identity<reg>, |
|
79 mpl::identity<nothing> |
|
80 >::type typex; |
|
81 return typex::invoke(); |
|
82 } |
|
83 |
|
84 const void_cast_detail::void_caster & m_vc; |
|
85 Derived & m_d; |
|
86 |
|
87 base_register(Derived & d) : |
|
88 m_vc(invoke()), |
|
89 m_d(d) |
|
90 {} |
|
91 Base & get_base() const { |
|
92 return m_d; |
|
93 } |
|
94 }; |
|
95 #else |
|
96 // only register void casts if the types are polymorphic |
|
97 template<class Base, class Derived> |
|
98 struct base_register{ |
|
99 struct nothing { |
|
100 static void invoke(){} |
|
101 }; |
|
102 struct reg{ |
|
103 static void invoke(){ |
|
104 void_cast_register<const Derived, const Base>( |
|
105 static_cast<const Derived *>(NULL), |
|
106 static_cast<const Base *>(NULL) |
|
107 ); |
|
108 } |
|
109 }; |
|
110 static void invoke(){ |
|
111 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< |
|
112 BOOST_DEDUCED_TYPENAME type_info_implementation<Base>::type::is_polymorphic, |
|
113 mpl::identity<reg>, |
|
114 mpl::identity<nothing> |
|
115 >::type typex; |
|
116 typex::invoke(); |
|
117 } |
|
118 }; |
|
119 #endif |
|
120 // get the base type for a given derived type |
|
121 // preserving the const-ness |
|
122 template<class B, class D> |
|
123 struct base_cast |
|
124 { |
|
125 typedef BOOST_DEDUCED_TYPENAME |
|
126 mpl::if_< |
|
127 is_const<D>, |
|
128 const B, |
|
129 B |
|
130 >::type type; |
|
131 BOOST_STATIC_ASSERT(is_const<type>::value == is_const<D>::value); |
|
132 }; |
|
133 } // namespace detail |
|
134 |
|
135 // metrowerks CodeWarrior |
|
136 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) |
|
137 template<class Base, class Derived> |
|
138 BOOST_DEDUCED_TYPENAME detail::base_cast<Base, Derived>::type & |
|
139 base_object(Derived &d) |
|
140 { |
|
141 BOOST_STATIC_ASSERT(( is_base_and_derived<Base,Derived>::value)); |
|
142 BOOST_STATIC_ASSERT(! is_pointer<Derived>::value); |
|
143 typedef BOOST_DEDUCED_TYPENAME detail::base_cast<Base, Derived>::type type; |
|
144 return detail::base_register<type, Derived>(d).get_base(); |
|
145 } |
|
146 // BORLAND |
|
147 #elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560)) |
|
148 template<class Base, class Derived> |
|
149 const Base & |
|
150 base_object(const Derived & d) |
|
151 { |
|
152 BOOST_STATIC_ASSERT(! is_pointer<Derived>::value); |
|
153 detail::base_register<Base, Derived>::invoke(); |
|
154 return static_cast<const Base &>(d); |
|
155 } |
|
156 #else |
|
157 template<class Base, class Derived> |
|
158 BOOST_DEDUCED_TYPENAME detail::base_cast<Base, Derived>::type & |
|
159 base_object(Derived &d) |
|
160 { |
|
161 BOOST_STATIC_ASSERT(( is_base_and_derived<Base,Derived>::value)); |
|
162 BOOST_STATIC_ASSERT(! is_pointer<Derived>::value); |
|
163 typedef BOOST_DEDUCED_TYPENAME detail::base_cast<Base, Derived>::type type; |
|
164 detail::base_register<type, Derived>::invoke(); |
|
165 return static_cast<type &>(d); |
|
166 } |
|
167 #endif |
|
168 |
|
169 } // namespace serialization |
|
170 } // namespace boost |
|
171 |
|
172 #endif // BOOST_SERIALIZATION_BASE_OBJECT_HPP |