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