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