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