69ff08ff |
1 | // Copyright (c) 1991-1999 Matra Datavision |
2 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
3 | // |
4 | // This file is part of Open CASCADE Technology software library. |
5 | // |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
11 | // |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
14 | |
15 | #ifndef _Standard_Type_HeaderFile |
16 | #define _Standard_Type_HeaderFile |
17 | |
18 | #include <Standard.hxx> |
e7195ab4 |
19 | #include <Standard_Handle.hxx> |
69ff08ff |
20 | #include <Standard_Transient.hxx> |
e7195ab4 |
21 | #include <Standard_OStream.hxx> |
69ff08ff |
22 | |
23 | #include <typeinfo> |
24 | |
e7195ab4 |
25 | //! Helper macro to get instance of a type descriptor for a class in a legacy way. |
f5f4ebd0 |
26 | #define STANDARD_TYPE(theType) theType::get_type_descriptor() |
e7195ab4 |
27 | |
28 | //! Helper macro to be included in definition of the classes inheriting |
f5f4ebd0 |
29 | //! Standard_Transient to enable use of OCCT RTTI. |
30 | //! |
31 | //! Inline version, does not require IMPLEMENT_STANDARD_RTTIEXT, but when used |
32 | //! for big hierarchies of classes may cause considerable increase of size of binaries. |
33 | #define DEFINE_STANDARD_RTTI_INLINE(Class,Base) \ |
e7195ab4 |
34 | public: \ |
35 | typedef Base base_type; \ |
36 | static const char* get_type_name () { return #Class; } \ |
f5f4ebd0 |
37 | static const Handle(Standard_Type)& get_type_descriptor () { return Standard_Type::Instance<Class>(); } \ |
79104795 |
38 | virtual const Handle(Standard_Type)& DynamicType() const Standard_OVERRIDE \ |
39 | { return STANDARD_TYPE(Class); } |
e7195ab4 |
40 | |
f5f4ebd0 |
41 | //! Helper macro to be included in definition of the classes inheriting |
42 | //! Standard_Transient to enable use of OCCT RTTI. |
43 | //! |
44 | //! Out-of-line version, requires IMPLEMENT_STANDARD_RTTIEXT. |
45 | #define DEFINE_STANDARD_RTTIEXT(Class,Base) \ |
46 | public: \ |
47 | typedef Base base_type; \ |
48 | static const char* get_type_name () { return #Class; } \ |
49 | Standard_EXPORT static const Handle(Standard_Type)& get_type_descriptor (); \ |
50 | Standard_EXPORT virtual const Handle(Standard_Type)& DynamicType() const Standard_OVERRIDE; |
51 | |
52 | //! Defines implementation of type descriptor and DynamicType() function |
53 | #define IMPLEMENT_STANDARD_RTTIEXT(Class,Base) \ |
54 | const Handle(Standard_Type)& Class::get_type_descriptor () { return Standard_Type::Instance<Class>(); } \ |
55 | const Handle(Standard_Type)& Class::DynamicType() const { return get_type_descriptor(); } |
56 | |
e7195ab4 |
57 | // forward declaration of type_instance class |
58 | namespace opencascade { |
59 | template <typename T> |
d9e90905 |
60 | class type_instance; |
e7195ab4 |
61 | } |
69ff08ff |
62 | |
63 | //! This class provides legacy interface (type descriptor) to run-time type |
64 | //! information (RTTI) for OCCT classes inheriting from Standard_Transient. |
65 | //! |
66 | //! In addition to features provided by standard C++ RTTI (type_info), |
67 | //! Standard_Type allows passing descriptor as an object and using it for |
68 | //! analysis of the type: |
69 | //! - get descriptor of a parent class |
70 | //! - get user-defined name of the class |
71 | //! - get size of the object |
72 | //! |
73 | //! Use static template method Instance() to get descriptor for a given type. |
74 | //! Objects supporting OCCT RTTI return their type descriptor by method DynamicType(). |
75 | //! |
76 | //! To be usable with OCCT type system, the class should provide: |
77 | //! - typedef base_type to its base class in the hierarchy |
78 | //! - method get_type_name() returning programmer-defined name of the class |
79 | //! (as a statically allocated constant C string or string literal) |
80 | //! |
81 | //! Note that user-defined name is used since typeid.name() is usually mangled in |
82 | //! compiler-dependent way. |
83 | //! |
84 | //! Only single chain of inheritance is supported, with a root base class Standard_Transient. |
85 | |
86 | class Standard_Type : public Standard_Transient |
87 | { |
88 | public: |
89 | |
90 | //! Returns the system type name of the class (typeinfo.name) |
91 | Standard_CString SystemName() const { return mySystemName; } |
92 | |
93 | //! Returns the given name of the class type (get_type_name) |
94 | Standard_CString Name() const { return myName; } |
95 | |
96 | //! Returns the size of the class instance in bytes |
97 | Standard_Size Size() const { return mySize; } |
98 | |
99 | //! Returns descriptor of the base class in the hierarchy |
100 | const Handle(Standard_Type)& Parent () const { return myParent; } |
101 | |
102 | //! Returns True if this type is the same as theOther, or inherits from theOther. |
103 | //! Note that multiple inheritance is not supported. |
104 | Standard_EXPORT Standard_Boolean SubType (const Handle(Standard_Type)& theOther) const; |
105 | |
106 | //! Returns True if this type is the same as theOther, or inherits from theOther. |
107 | //! Note that multiple inheritance is not supported. |
108 | Standard_EXPORT Standard_Boolean SubType (const Standard_CString theOther) const; |
109 | |
110 | //! Prints type (address of descriptor + name) to a stream |
111 | Standard_EXPORT void Print (Standard_OStream& theStream) const; |
112 | |
113 | //! Template function returning instance of the type descriptor for an argument class. |
114 | //! |
115 | //! For optimization, each type is registered only once (due to use of the static variable). |
116 | //! |
117 | //! See helper macro DEFINE_STANDARD_RTTI for defining these items in the class. |
118 | template <class T> |
119 | static const Handle(Standard_Type)& Instance() |
120 | { |
121 | return opencascade::type_instance<T>::get(); |
122 | } |
123 | |
124 | //! Register a type; returns either new or existing descriptor. |
125 | //! |
126 | //! @param theSystemName name of the class as returned by typeid(class).name() |
127 | //! @param theName name of the class to be stored in Name field |
128 | //! @param theSize size of the class instance |
129 | //! @param theParent base class in the Transient hierarchy |
130 | //! |
131 | //! Note that this function is intended for use by opencascade::type_instance only. |
132 | Standard_EXPORT static |
e7195ab4 |
133 | Standard_Type* Register (const char* theSystemName, const char* theName, |
134 | Standard_Size theSize, const Handle(Standard_Type)& theParent); |
69ff08ff |
135 | |
136 | //! Destructor removes the type from the registry |
137 | Standard_EXPORT ~Standard_Type (); |
138 | |
139 | // Define own RTTI |
f5f4ebd0 |
140 | DEFINE_STANDARD_RTTIEXT(Standard_Type,Standard_Transient) |
69ff08ff |
141 | |
142 | private: |
143 | |
144 | //! Constructor is private |
145 | Standard_Type (const char* theSystemName, const char* theName, |
a0218ba1 |
146 | Standard_Size theSize, const Handle(Standard_Type)& theParent); |
69ff08ff |
147 | |
148 | private: |
149 | Standard_CString mySystemName; //!< System name of the class (typeinfo.name) |
150 | Standard_CString myName; //!< Given name of the class |
151 | Standard_Size mySize; //!< Size of the class instance, in bytes |
152 | Handle(Standard_Type) myParent; //!< Type descriptor of parent class |
153 | }; |
154 | |
155 | namespace opencascade { |
156 | |
d9e90905 |
157 | //! Template class providing instantiation of type descriptors as singletons. |
158 | //! The descriptors are defined as static variables in function get(), which |
159 | //! is essential to ensure that they are initialized in correct sequence. |
160 | //! |
161 | //! For compilers that do not provide thread-safe initialization of static |
162 | //! variables (C++11 feature, N2660), additional global variable is |
163 | //! defined for each type to hold its type descriptor. These globals ensure |
164 | //! that all types get initialized during the library loading and thus no |
165 | //! concurrency occurs when type system is accessed from multiple threads. |
69ff08ff |
166 | template <typename T> |
d9e90905 |
167 | class type_instance |
69ff08ff |
168 | { |
d9e90905 |
169 | static Handle(Standard_Type) myInstance; |
170 | public: |
69ff08ff |
171 | static const Handle(Standard_Type)& get (); |
172 | }; |
173 | |
174 | //! Specialization of type descriptor instance for void; returns null handle |
175 | template <> |
d9e90905 |
176 | class type_instance<void> |
69ff08ff |
177 | { |
d9e90905 |
178 | public: |
69ff08ff |
179 | Standard_EXPORT static Handle(Standard_Type) get () { return 0; } |
180 | }; |
181 | |
182 | // Implementation of static function returning instance of the |
183 | // type descriptor |
184 | template <typename T> |
185 | const Handle(Standard_Type)& type_instance<T>::get () |
186 | { |
8bb8064e |
187 | #if (defined(_MSC_VER) && _MSC_VER < 1800) || \ |
188 | (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)) && \ |
189 | ! defined(__clang__) && ! defined(__INTEL_COMPILER)) |
d9e90905 |
190 | // ensure that myInstance is instantiated |
191 | (void)myInstance; |
8bb8064e |
192 | #endif |
d9e90905 |
193 | |
69ff08ff |
194 | // static variable inside function ensures that descriptors |
195 | // are initialized in correct sequence |
196 | static Handle(Standard_Type) anInstance = |
197 | Standard_Type::Register (typeid(T).name(), T::get_type_name(), sizeof(T), |
198 | type_instance<typename T::base_type>::get()); |
199 | return anInstance; |
200 | } |
201 | |
d9e90905 |
202 | // Static class field is defined to ensure initialization of all type |
203 | // descriptors at load time of the library on compilers not supporting N2660: |
204 | // - VC++ below 14 (VS 2015) |
205 | // - GCC below 4.3 |
206 | // Intel compiler reports itself as GCC on Linux and VC++ on Windows, |
207 | // and is claimed to support N2660 on Linux and on Windows "in VS2015 mode". |
208 | // CLang should support N2660 since version 2.9, but it is not clear how to |
209 | // check its version reliably (on Linux it says it is GCC 4.2). |
210 | #if (defined(_MSC_VER) && _MSC_VER < 1800) || \ |
211 | (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)) && \ |
212 | ! defined(__clang__) && ! defined(__INTEL_COMPILER)) |
213 | |
214 | template <typename T> |
215 | Handle(Standard_Type) type_instance<T>::myInstance (get()); |
216 | |
217 | #endif |
69ff08ff |
218 | } |
219 | |
220 | //! Operator printing type descriptor to stream |
221 | inline Standard_OStream& operator << (Standard_OStream& theStream, const Handle(Standard_Type)& theType) |
222 | { |
223 | theType->Print (theStream); |
224 | return theStream; |
225 | } |
226 | |
e7195ab4 |
227 | //! Definition of Handle_Standard_Type as typedef for compatibility |
228 | DEFINE_STANDARD_HANDLE(Standard_Type,Standard_Transient) |
229 | |
69ff08ff |
230 | #endif // _Standard_Type_HeaderFile |