1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        wx/typeinfo.h
3 // Purpose:     wxTypeId implementation
4 // Author:      Jaakko Salli
5 // Created:     2009-11-19
6 // Copyright:   (c) wxWidgets Team
7 // Licence:     wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9 
10 #ifndef _WX_TYPEINFO_H_
11 #define _WX_TYPEINFO_H_
12 
13 //
14 // This file defines wxTypeId macro that should be used internally in
15 // wxWidgets instead of typeid(), for compatibility with builds that do
16 // not implement C++ RTTI. Also, type defining macros in this file are
17 // intended for internal use only at this time and may change in future
18 // versions.
19 //
20 // The reason why we need this simple RTTI system in addition to the older
21 // wxObject-based one is that the latter does not work in template
22 // classes.
23 //
24 
25 #include "wx/defs.h"
26 
27 #ifndef wxNO_RTTI
28 
29 //
30 // Let's trust that Visual C++ versions 9.0 and later implement C++
31 // RTTI well enough, so we can use it and work around harmless memory
32 // leaks reported by the static run-time libraries.
33 //
34 #if wxCHECK_VISUALC_VERSION(9)
35     #define wxTRUST_CPP_RTTI    1
36 #else
37     #define wxTRUST_CPP_RTTI    0
38 #endif
39 
40 #include <typeinfo>
41 #include <string.h>
42 
43 #define _WX_DECLARE_TYPEINFO_CUSTOM(CLS, IDENTFUNC)
44 #define WX_DECLARE_TYPEINFO_INLINE(CLS)
45 #define WX_DECLARE_TYPEINFO(CLS)
46 #define WX_DEFINE_TYPEINFO(CLS)
47 #define WX_DECLARE_ABSTRACT_TYPEINFO(CLS)
48 
49 #if wxTRUST_CPP_RTTI
50 
51 #define wxTypeId    typeid
52 
53 #else /*  !wxTRUST_CPP_RTTI */
54 
55 //
56 // For improved type-safety, let's make the check using class name
57 // comparison. Most modern compilers already do this, but we cannot
58 // rely on all supported compilers to work this well. However, in
59 // cases where we'd know that typeid() would be flawless (as such),
60 // wxTypeId could of course simply be defined as typeid.
61 //
62 
63 class wxTypeIdentifier
64 {
65 public:
wxTypeIdentifier(const char * className)66     wxTypeIdentifier(const char* className)
67     {
68         m_className = className;
69     }
70 
71     bool operator==(const wxTypeIdentifier& other) const
72     {
73         return strcmp(m_className, other.m_className) == 0;
74     }
75 
76     bool operator!=(const wxTypeIdentifier& other) const
77     {
78         return !(*this == other);
79     }
80 private:
81     const char* m_className;
82 };
83 
84 #define wxTypeId(OBJ) wxTypeIdentifier(typeid(OBJ).name())
85 
86 #endif /*  wxTRUST_CPP_RTTI/!wxTRUST_CPP_RTTI */
87 
88 #else // if !wxNO_RTTI
89 
90 #define wxTRUST_CPP_RTTI    0
91 
92 //
93 // When C++ RTTI is not available, we will have to make the type comparison
94 // using pointer to a dummy static member function. This will fail if
95 // declared type is used across DLL boundaries, although using
96 // WX_DECLARE_TYPEINFO() and WX_DEFINE_TYPEINFO() pair instead of
97 // WX_DECLARE_TYPEINFO_INLINE() should fix this. However, that approach is
98 // usually not possible when type info needs to be declared for a template
99 // class.
100 //
101 
102 typedef void (*wxTypeIdentifier)();
103 
104 // Use this macro to declare type info with specified static function
105 // IDENTFUNC used as type identifier. Usually you should only use
106 // WX_DECLARE_TYPEINFO() or WX_DECLARE_TYPEINFO_INLINE() however.
107 #define _WX_DECLARE_TYPEINFO_CUSTOM(CLS, IDENTFUNC) \
108 public: \
109     virtual wxTypeIdentifier GetWxTypeId() const wxOVERRIDE \
110     { \
111         return reinterpret_cast<wxTypeIdentifier> \
112             (&IDENTFUNC); \
113     }
114 
115 // Use this macro to declare type info with externally specified
116 // type identifier, defined with WX_DEFINE_TYPEINFO().
117 #define WX_DECLARE_TYPEINFO(CLS) \
118 private: \
119     static CLS sm_wxClassInfo(); \
120 _WX_DECLARE_TYPEINFO_CUSTOM(CLS, sm_wxClassInfo)
121 
122 // Use this macro to implement type identifier function required by
123 // WX_DECLARE_TYPEINFO().
124 // NOTE: CLS is required to have default ctor. If it doesn't
125 //       already, you should provide a private dummy one.
126 #define WX_DEFINE_TYPEINFO(CLS) \
127 CLS CLS::sm_wxClassInfo() { return CLS(); }
128 
129 // Use this macro to declare type info fully inline in class.
130 // NOTE: CLS is required to have default ctor. If it doesn't
131 //       already, you should provide a private dummy one.
132 #define WX_DECLARE_TYPEINFO_INLINE(CLS) \
133 private: \
134     static CLS sm_wxClassInfo() { return CLS(); } \
135 _WX_DECLARE_TYPEINFO_CUSTOM(CLS, sm_wxClassInfo)
136 
137 #define wxTypeId(OBJ) (OBJ).GetWxTypeId()
138 
139 // Because abstract classes cannot be instantiated, we use
140 // this macro to define pure virtual type interface for them.
141 #define WX_DECLARE_ABSTRACT_TYPEINFO(CLS) \
142 public: \
143     virtual wxTypeIdentifier GetWxTypeId() const = 0;
144 
145 #endif // wxNO_RTTI/!wxNO_RTTI
146 
147 #endif // _WX_TYPEINFO_H_
148