]>
Commit | Line | Data |
---|---|---|
1 | #ifndef BOOST_STATECHART_DETAIL_RTTI_POLICY_HPP_INCLUDED | |
2 | #define BOOST_STATECHART_DETAIL_RTTI_POLICY_HPP_INCLUDED | |
3 | ////////////////////////////////////////////////////////////////////////////// | |
4 | // Copyright 2002-2008 Andreas Huber Doenni | |
5 | // Distributed under the Boost Software License, Version 1.0. (See accompany- | |
6 | // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ////////////////////////////////////////////////////////////////////////////// | |
8 | ||
9 | ||
10 | ||
11 | #include <boost/assert.hpp> | |
12 | #include <boost/config.hpp> // BOOST_MSVC | |
13 | #include <boost/detail/workaround.hpp> | |
14 | ||
15 | #include <typeinfo> // std::type_info | |
16 | ||
17 | ||
18 | ||
19 | namespace boost | |
20 | { | |
21 | namespace statechart | |
22 | { | |
23 | namespace detail | |
24 | { | |
25 | ||
26 | ||
27 | ||
28 | ////////////////////////////////////////////////////////////////////////////// | |
29 | struct id_provider | |
30 | { | |
31 | const void * pCustomId_; | |
32 | #if defined( BOOST_ENABLE_ASSERT_HANDLER ) || !defined( NDEBUG ) | |
33 | const std::type_info * pCustomIdType_; | |
34 | #endif | |
35 | }; | |
36 | ||
37 | template< class MostDerived > | |
38 | struct id_holder | |
39 | { | |
40 | static id_provider idProvider_; | |
41 | }; | |
42 | ||
43 | template< class MostDerived > | |
44 | id_provider id_holder< MostDerived >::idProvider_; | |
45 | ||
46 | ||
47 | ||
48 | ////////////////////////////////////////////////////////////////////////////// | |
49 | struct rtti_policy | |
50 | { | |
51 | #ifdef BOOST_STATECHART_USE_NATIVE_RTTI | |
52 | class id_type | |
53 | { | |
54 | public: | |
55 | //////////////////////////////////////////////////////////////////////// | |
56 | explicit id_type( const std::type_info & id ) : id_( id ) {} | |
57 | ||
58 | bool operator==( id_type right ) const | |
59 | { | |
60 | return id_ == right.id_ != 0; | |
61 | } | |
62 | bool operator!=( id_type right ) const { return !( *this == right ); } | |
63 | ||
64 | bool operator<( id_type right ) const | |
65 | { | |
66 | return id_.before( right.id_ ) != 0; | |
67 | } | |
68 | bool operator>( id_type right ) const { return right < *this; } | |
69 | bool operator>=( id_type right ) const { return !( *this < right ); } | |
70 | bool operator<=( id_type right ) const { return !( right < *this ); } | |
71 | ||
72 | private: | |
73 | //////////////////////////////////////////////////////////////////////// | |
74 | const std::type_info & id_; | |
75 | }; | |
76 | ||
77 | typedef bool id_provider_type; // dummy | |
78 | #else | |
79 | typedef const void * id_type; | |
80 | typedef const id_provider * id_provider_type; | |
81 | #endif | |
82 | ||
83 | //////////////////////////////////////////////////////////////////////////// | |
84 | template< class Base > | |
85 | class rtti_base_type : public Base | |
86 | { | |
87 | public: | |
88 | //////////////////////////////////////////////////////////////////////// | |
89 | typedef rtti_policy::id_type id_type; | |
90 | ||
91 | id_type dynamic_type() const | |
92 | { | |
93 | #ifdef BOOST_STATECHART_USE_NATIVE_RTTI | |
94 | return id_type( typeid( *this ) ); | |
95 | #else | |
96 | return idProvider_; | |
97 | #endif | |
98 | } | |
99 | ||
100 | #ifndef BOOST_STATECHART_USE_NATIVE_RTTI | |
101 | template< typename CustomId > | |
102 | const CustomId * custom_dynamic_type_ptr() const | |
103 | { | |
104 | BOOST_ASSERT( | |
105 | ( idProvider_->pCustomId_ == 0 ) || | |
106 | ( *idProvider_->pCustomIdType_ == typeid( CustomId ) ) ); | |
107 | return static_cast< const CustomId * >( idProvider_->pCustomId_ ); | |
108 | } | |
109 | #endif | |
110 | ||
111 | protected: | |
112 | #ifdef BOOST_STATECHART_USE_NATIVE_RTTI | |
113 | rtti_base_type( id_provider_type ) {} | |
114 | ||
115 | //////////////////////////////////////////////////////////////////////// | |
116 | #if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT( 4 ) ) | |
117 | // We make the destructor virtual for GCC because with this compiler | |
118 | // there is currently no way to disable the "has virtual functions but | |
119 | // non-virtual destructor" warning on a class by class basis. Although | |
120 | // it can be done on the compiler command line with | |
121 | // -Wno-non-virtual-dtor, this is undesirable as this would also | |
122 | // suppress legitimate warnings for types that are not states. | |
123 | virtual ~rtti_base_type() {} | |
124 | #else | |
125 | ~rtti_base_type() {} | |
126 | #endif | |
127 | ||
128 | private: | |
129 | //////////////////////////////////////////////////////////////////////// | |
130 | // For typeid( *this ) to return a value that corresponds to the most- | |
131 | // derived type, we need to have a vptr. Since this type does not | |
132 | // contain any virtual functions we need to artificially declare one so. | |
133 | virtual void dummy() {} | |
134 | #else | |
135 | rtti_base_type( | |
136 | id_provider_type idProvider | |
137 | ) : | |
138 | idProvider_( idProvider ) | |
139 | { | |
140 | } | |
141 | ||
142 | ~rtti_base_type() {} | |
143 | ||
144 | private: | |
145 | //////////////////////////////////////////////////////////////////////// | |
146 | id_provider_type idProvider_; | |
147 | #endif | |
148 | }; | |
149 | ||
150 | //////////////////////////////////////////////////////////////////////////// | |
151 | template< class MostDerived, class Base > | |
152 | class rtti_derived_type : public Base | |
153 | { | |
154 | public: | |
155 | //////////////////////////////////////////////////////////////////////// | |
156 | static id_type static_type() | |
157 | { | |
158 | #ifdef BOOST_STATECHART_USE_NATIVE_RTTI | |
159 | return id_type( typeid( const MostDerived ) ); | |
160 | #else | |
161 | return &id_holder< MostDerived >::idProvider_; | |
162 | #endif | |
163 | } | |
164 | ||
165 | #ifndef BOOST_STATECHART_USE_NATIVE_RTTI | |
166 | template< class CustomId > | |
167 | static const CustomId * custom_static_type_ptr() | |
168 | { | |
169 | BOOST_ASSERT( | |
170 | ( id_holder< MostDerived >::idProvider_.pCustomId_ == 0 ) || | |
171 | ( *id_holder< MostDerived >::idProvider_.pCustomIdType_ == | |
172 | typeid( CustomId ) ) ); | |
173 | return static_cast< const CustomId * >( | |
174 | id_holder< MostDerived >::idProvider_.pCustomId_ ); | |
175 | } | |
176 | ||
177 | template< class CustomId > | |
178 | static void custom_static_type_ptr( const CustomId * pCustomId ) | |
179 | { | |
180 | #if defined( BOOST_ENABLE_ASSERT_HANDLER ) || !defined( NDEBUG ) | |
181 | id_holder< MostDerived >::idProvider_.pCustomIdType_ = | |
182 | &typeid( CustomId ); | |
183 | #endif | |
184 | id_holder< MostDerived >::idProvider_.pCustomId_ = pCustomId; | |
185 | } | |
186 | #endif | |
187 | ||
188 | protected: | |
189 | //////////////////////////////////////////////////////////////////////// | |
190 | ~rtti_derived_type() {} | |
191 | ||
192 | #ifdef BOOST_STATECHART_USE_NATIVE_RTTI | |
193 | rtti_derived_type() : Base( false ) {} | |
194 | #else | |
195 | rtti_derived_type() : Base( &id_holder< MostDerived >::idProvider_ ) {} | |
196 | #endif | |
197 | }; | |
198 | }; | |
199 | ||
200 | ||
201 | ||
202 | } // namespace detail | |
203 | } // namespace statechart | |
204 | } // namespace boost | |
205 | ||
206 | ||
207 | ||
208 | #endif |