]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: wx/xtitypes.h | |
3 | // Purpose: enum, set, basic types support | |
4 | // Author: Stefan Csomor | |
5 | // Modified by: Francesco Montorsi | |
6 | // Created: 27/07/03 | |
7 | // Copyright: (c) 1997 Julian Smart | |
8 | // (c) 2003 Stefan Csomor | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | #ifndef _XTITYPES_H_ | |
13 | #define _XTITYPES_H_ | |
14 | ||
15 | #include "wx/defs.h" | |
16 | ||
17 | #if wxUSE_EXTENDED_RTTI | |
18 | ||
19 | #include "wx/string.h" | |
20 | #include "wx/hashmap.h" | |
21 | #include "wx/arrstr.h" | |
22 | #include "wx/flags.h" | |
23 | #include "wx/intl.h" | |
24 | #include "wx/log.h" | |
25 | #include <typeinfo> | |
26 | ||
27 | class WXDLLIMPEXP_BASE wxClassInfo; | |
28 | ||
29 | // ---------------------------------------------------------------------------- | |
30 | // Enum Support | |
31 | // | |
32 | // In the header files XTI requires no change from pure c++ code, however in the | |
33 | // implementation, an enum needs to be enumerated eg: | |
34 | // | |
35 | // wxBEGIN_ENUM( wxFlavor ) | |
36 | // wxENUM_MEMBER( Vanilla ) | |
37 | // wxENUM_MEMBER( Chocolate ) | |
38 | // wxENUM_MEMBER( Strawberry ) | |
39 | // wxEND_ENUM( wxFlavor ) | |
40 | // ---------------------------------------------------------------------------- | |
41 | ||
42 | struct WXDLLIMPEXP_BASE wxEnumMemberData | |
43 | { | |
44 | const wxChar* m_name; | |
45 | int m_value; | |
46 | }; | |
47 | ||
48 | class WXDLLIMPEXP_BASE wxEnumData | |
49 | { | |
50 | public: | |
51 | wxEnumData( wxEnumMemberData* data ); | |
52 | ||
53 | // returns true if the member has been found and sets the int value | |
54 | // pointed to accordingly (if ptr != null ) | |
55 | // if not found returns false, value left unchanged | |
56 | bool HasEnumMemberValue( const wxChar *name, int *value = NULL ) const; | |
57 | ||
58 | // returns the value of the member, if not found in debug mode an | |
59 | // assert is issued, in release 0 is returned | |
60 | int GetEnumMemberValue(const wxChar *name ) const; | |
61 | ||
62 | // returns the name of the enum member having the passed in value | |
63 | // returns an emtpy string if not found | |
64 | const wxChar *GetEnumMemberName(int value) const; | |
65 | ||
66 | // returns the number of members in this enum | |
67 | int GetEnumCount() const { return m_count; } | |
68 | ||
69 | // returns the value of the nth member | |
70 | int GetEnumMemberValueByIndex( int n ) const; | |
71 | ||
72 | // returns the value of the nth member | |
73 | const wxChar *GetEnumMemberNameByIndex( int n ) const; | |
74 | ||
75 | private: | |
76 | wxEnumMemberData *m_members; | |
77 | int m_count; | |
78 | }; | |
79 | ||
80 | #define wxBEGIN_ENUM( e ) \ | |
81 | wxEnumMemberData s_enumDataMembers##e[] = { | |
82 | ||
83 | #define wxENUM_MEMBER( v ) { wxT(#v), v }, | |
84 | ||
85 | #define wxEND_ENUM( e ) \ | |
86 | { NULL, 0 } }; \ | |
87 | wxEnumData s_enumData##e( s_enumDataMembers##e ); \ | |
88 | wxEnumData *wxGetEnumData(e) { return &s_enumData##e; } \ | |
89 | template<> void wxStringReadValue(const wxString& s, e &data ) \ | |
90 | { data = (e) s_enumData##e.GetEnumMemberValue(s.c_str()); } \ | |
91 | template<> void wxStringWriteValue(wxString &s, const e &data ) \ | |
92 | { s = s_enumData##e.GetEnumMemberName((int)data); } \ | |
93 | void FromLong##e( long data, wxAny& result ) \ | |
94 | { result = wxAny((e)data); } \ | |
95 | void ToLong##e( const wxAny& data, long &result ) \ | |
96 | { result = (long) (data).As(static_cast<e*>(NULL)); } \ | |
97 | \ | |
98 | wxTO_STRING_IMP( e ) \ | |
99 | wxFROM_STRING_IMP( e ) \ | |
100 | wxEnumTypeInfo s_typeInfo##e(wxT_ENUM, &s_enumData##e, \ | |
101 | &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \ | |
102 | &FromLong##e, typeid(e).name() ); | |
103 | ||
104 | ||
105 | // ---------------------------------------------------------------------------- | |
106 | // Set Support | |
107 | // | |
108 | // in the header : | |
109 | // | |
110 | // enum wxFlavor | |
111 | // { | |
112 | // Vanilla, | |
113 | // Chocolate, | |
114 | // Strawberry, | |
115 | // }; | |
116 | // | |
117 | // typedef wxBitset<wxFlavor> wxCoupe; | |
118 | // | |
119 | // in the implementation file : | |
120 | // | |
121 | // wxBEGIN_ENUM( wxFlavor ) | |
122 | // wxENUM_MEMBER( Vanilla ) | |
123 | // wxENUM_MEMBER( Chocolate ) | |
124 | // wxENUM_MEMBER( Strawberry ) | |
125 | // wxEND_ENUM( wxFlavor ) | |
126 | // | |
127 | // wxIMPLEMENT_SET_STREAMING( wxCoupe, wxFlavor ) | |
128 | // | |
129 | // implementation note: no partial specialization for streaming, but a delegation | |
130 | // to a different class | |
131 | // | |
132 | // ---------------------------------------------------------------------------- | |
133 | ||
134 | void WXDLLIMPEXP_BASE wxSetStringToArray( const wxString &s, wxArrayString &array ); | |
135 | ||
136 | template<typename e> | |
137 | void wxSetFromString(const wxString &s, wxBitset<e> &data ) | |
138 | { | |
139 | wxEnumData* edata = wxGetEnumData((e) 0); | |
140 | data.reset(); | |
141 | ||
142 | wxArrayString array; | |
143 | wxSetStringToArray( s, array ); | |
144 | wxString flag; | |
145 | for ( int i = 0; i < array.Count(); ++i ) | |
146 | { | |
147 | flag = array[i]; | |
148 | int ivalue; | |
149 | if ( edata->HasEnumMemberValue( flag.c_str(), &ivalue ) ) | |
150 | { | |
151 | data.set( (e) ivalue ); | |
152 | } | |
153 | } | |
154 | } | |
155 | ||
156 | template<typename e> | |
157 | void wxSetToString( wxString &s, const wxBitset<e> &data ) | |
158 | { | |
159 | wxEnumData* edata = wxGetEnumData((e) 0); | |
160 | int count = edata->GetEnumCount(); | |
161 | int i; | |
162 | s.Clear(); | |
163 | for ( i = 0; i < count; i++ ) | |
164 | { | |
165 | e value = (e) edata->GetEnumMemberValueByIndex(i); | |
166 | if ( data.test( value ) ) | |
167 | { | |
168 | // this could also be done by the templated calls | |
169 | if ( !s.empty() ) | |
170 | s += wxT("|"); | |
171 | s += edata->GetEnumMemberNameByIndex(i); | |
172 | } | |
173 | } | |
174 | } | |
175 | ||
176 | #define wxIMPLEMENT_SET_STREAMING(SetName,e) \ | |
177 | template<> void wxStringReadValue(const wxString &s, wxBitset<e> &data ) \ | |
178 | { wxSetFromString( s, data ); } \ | |
179 | template<> void wxStringWriteValue( wxString &s, const wxBitset<e> &data ) \ | |
180 | { wxSetToString( s, data ); } \ | |
181 | void FromLong##SetName( long data, wxAny& result ) \ | |
182 | { result = wxAny(SetName((unsigned long)data)); } \ | |
183 | void ToLong##SetName( const wxAny& data, long &result ) \ | |
184 | { result = (long) (data).As(static_cast<SetName*>(NULL)).to_ulong(); } \ | |
185 | wxTO_STRING_IMP( SetName ) \ | |
186 | wxFROM_STRING_IMP( SetName ) \ | |
187 | wxEnumTypeInfo s_typeInfo##SetName(wxT_SET, &s_enumData##e, \ | |
188 | &wxTO_STRING( SetName ), &wxFROM_STRING( SetName ), \ | |
189 | &ToLong##SetName, &FromLong##SetName, typeid(SetName).name() ); | |
190 | ||
191 | template<typename e> | |
192 | void wxFlagsFromString(const wxString &s, e &data ) | |
193 | { | |
194 | wxEnumData* edata = wxGetEnumData((e*) 0); | |
195 | data.m_data = 0; | |
196 | ||
197 | wxArrayString array; | |
198 | wxSetStringToArray( s, array ); | |
199 | wxString flag; | |
200 | for ( size_t i = 0; i < array.Count(); ++i ) | |
201 | { | |
202 | flag = array[i]; | |
203 | int ivalue; | |
204 | if ( edata->HasEnumMemberValue( flag.c_str(), &ivalue ) ) | |
205 | { | |
206 | data.m_data |= ivalue; | |
207 | } | |
208 | } | |
209 | } | |
210 | ||
211 | template<typename e> | |
212 | void wxFlagsToString( wxString &s, const e& data ) | |
213 | { | |
214 | wxEnumData* edata = wxGetEnumData((e*) 0); | |
215 | int count = edata->GetEnumCount(); | |
216 | int i; | |
217 | s.Clear(); | |
218 | long dataValue = data.m_data; | |
219 | for ( i = 0; i < count; i++ ) | |
220 | { | |
221 | int value = edata->GetEnumMemberValueByIndex(i); | |
222 | // make this to allow for multi-bit constants to work | |
223 | if ( value && ( dataValue & value ) == value ) | |
224 | { | |
225 | // clear the flags we just set | |
226 | dataValue &= ~value; | |
227 | // this could also be done by the templated calls | |
228 | if ( !s.empty() ) | |
229 | s +=wxT("|"); | |
230 | s += edata->GetEnumMemberNameByIndex(i); | |
231 | } | |
232 | } | |
233 | } | |
234 | ||
235 | #define wxBEGIN_FLAGS( e ) \ | |
236 | wxEnumMemberData s_enumDataMembers##e[] = { | |
237 | ||
238 | #define wxFLAGS_MEMBER( v ) { wxT(#v), static_cast<int>(v) }, | |
239 | ||
240 | #define wxEND_FLAGS( e ) \ | |
241 | { NULL, 0 } }; \ | |
242 | wxEnumData s_enumData##e( s_enumDataMembers##e ); \ | |
243 | wxEnumData *wxGetEnumData(e*) { return &s_enumData##e; } \ | |
244 | template<> void wxStringReadValue(const wxString &s, e &data ) \ | |
245 | { wxFlagsFromString<e>( s, data ); } \ | |
246 | template<> void wxStringWriteValue( wxString &s, const e& data ) \ | |
247 | { wxFlagsToString<e>( s, data ); } \ | |
248 | void FromLong##e( long data, wxAny& result ) \ | |
249 | { result = wxAny(e(data)); } \ | |
250 | void ToLong##e( const wxAny& data, long &result ) \ | |
251 | { result = (long) (data).As(static_cast<e*>(NULL)).m_data; } \ | |
252 | wxTO_STRING_IMP( e ) \ | |
253 | wxFROM_STRING_IMP( e ) \ | |
254 | wxEnumTypeInfo s_typeInfo##e(wxT_SET, &s_enumData##e, \ | |
255 | &wxTO_STRING( e ), &wxFROM_STRING( e ), &ToLong##e, \ | |
256 | &FromLong##e, typeid(e).name() ); | |
257 | ||
258 | // ---------------------------------------------------------------------------- | |
259 | // Type Information | |
260 | // ---------------------------------------------------------------------------- | |
261 | ||
262 | // All data exposed by the RTTI is characterized using the following classes. | |
263 | // The first characterization is done by wxTypeKind. All enums up to and including | |
264 | // wxT_CUSTOM represent so called simple types. These cannot be divided any further. | |
265 | // They can be converted to and from wxStrings, that's all. | |
266 | // Other wxTypeKinds can instead be splitted recursively into smaller parts until | |
267 | // the simple types are reached. | |
268 | ||
269 | enum wxTypeKind | |
270 | { | |
271 | wxT_VOID = 0, // unknown type | |
272 | wxT_BOOL, | |
273 | wxT_CHAR, | |
274 | wxT_UCHAR, | |
275 | wxT_INT, | |
276 | wxT_UINT, | |
277 | wxT_LONG, | |
278 | wxT_ULONG, | |
279 | wxT_LONGLONG, | |
280 | wxT_ULONGLONG, | |
281 | wxT_FLOAT, | |
282 | wxT_DOUBLE, | |
283 | wxT_STRING, // must be wxString | |
284 | wxT_SET, // must be wxBitset<> template | |
285 | wxT_ENUM, | |
286 | wxT_CUSTOM, // user defined type (e.g. wxPoint) | |
287 | ||
288 | wxT_LAST_SIMPLE_TYPE_KIND = wxT_CUSTOM, | |
289 | ||
290 | wxT_OBJECT_PTR, // object reference | |
291 | wxT_OBJECT, // embedded object | |
292 | wxT_COLLECTION, // collection | |
293 | ||
294 | wxT_DELEGATE, // for connecting against an event source | |
295 | ||
296 | wxT_LAST_TYPE_KIND = wxT_DELEGATE // sentinel for bad data, asserts, debugging | |
297 | }; | |
298 | ||
299 | class WXDLLIMPEXP_BASE wxAny; | |
300 | class WXDLLIMPEXP_BASE wxTypeInfo; | |
301 | ||
302 | WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxTypeInfo*, wxTypeInfoMap, class WXDLLIMPEXP_BASE ); | |
303 | ||
304 | class WXDLLIMPEXP_BASE wxTypeInfo | |
305 | { | |
306 | public: | |
307 | typedef void (*wxVariant2StringFnc)( const wxAny& data, wxString &result ); | |
308 | typedef void (*wxString2VariantFnc)( const wxString& data, wxAny &result ); | |
309 | ||
310 | wxTypeInfo(wxTypeKind kind, | |
311 | wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL, | |
312 | const wxString &name = wxEmptyString): | |
313 | m_toString(to), m_fromString(from), m_kind(kind), m_name(name) | |
314 | { | |
315 | Register(); | |
316 | } | |
317 | #if 0 // wxUSE_UNICODE | |
318 | wxTypeInfo(wxTypeKind kind, | |
319 | wxVariant2StringFnc to, wxString2VariantFnc from, | |
320 | const char *name): | |
321 | m_toString(to), m_fromString(from), m_kind(kind), | |
322 | m_name(wxString::FromAscii(name)) | |
323 | { | |
324 | Register(); | |
325 | } | |
326 | #endif | |
327 | ||
328 | virtual ~wxTypeInfo() | |
329 | { | |
330 | Unregister(); | |
331 | } | |
332 | ||
333 | // return the kind of this type (wxT_... constants) | |
334 | wxTypeKind GetKind() const { return m_kind; } | |
335 | ||
336 | // returns the unique name of this type | |
337 | const wxString& GetTypeName() const { return m_name; } | |
338 | ||
339 | // is this type a delegate type | |
340 | bool IsDelegateType() const { return m_kind == wxT_DELEGATE; } | |
341 | ||
342 | // is this type a custom type | |
343 | bool IsCustomType() const { return m_kind == wxT_CUSTOM; } | |
344 | ||
345 | // is this type an object type | |
346 | bool IsObjectType() const { return m_kind == wxT_OBJECT || m_kind == wxT_OBJECT_PTR; } | |
347 | ||
348 | // can the content of this type be converted to and from strings ? | |
349 | bool HasStringConverters() const { return m_toString != NULL && m_fromString != NULL; } | |
350 | ||
351 | // convert a wxAny holding data of this type into a string | |
352 | void ConvertToString( const wxAny& data, wxString &result ) const | |
353 | { | |
354 | if ( m_toString ) | |
355 | (*m_toString)( data, result ); | |
356 | else | |
357 | wxLogError( wxGetTranslation(wxT("String conversions not supported")) ); | |
358 | } | |
359 | ||
360 | // convert a string into a wxAny holding the corresponding data in this type | |
361 | void ConvertFromString( const wxString& data, wxAny &result ) const | |
362 | { | |
363 | if( m_fromString ) | |
364 | (*m_fromString)( data, result ); | |
365 | else | |
366 | wxLogError( wxGetTranslation(wxT("String conversions not supported")) ); | |
367 | } | |
368 | ||
369 | // statics: | |
370 | ||
371 | // looks for the corresponding type, will return NULL if not found | |
372 | static wxTypeInfo *FindType( const wxString& typeName ); | |
373 | private: | |
374 | void Register(); | |
375 | void Unregister(); | |
376 | ||
377 | wxVariant2StringFnc m_toString; | |
378 | wxString2VariantFnc m_fromString; | |
379 | ||
380 | wxTypeKind m_kind; | |
381 | wxString m_name; | |
382 | ||
383 | // the static list of all types we know about | |
384 | static wxTypeInfoMap* ms_typeTable; | |
385 | }; | |
386 | ||
387 | class WXDLLIMPEXP_BASE wxBuiltInTypeInfo : public wxTypeInfo | |
388 | { | |
389 | public: | |
390 | wxBuiltInTypeInfo( wxTypeKind kind, wxVariant2StringFnc to = NULL, | |
391 | wxString2VariantFnc from = NULL, | |
392 | const wxString &name = wxEmptyString ) : | |
393 | wxTypeInfo( kind, to, from, name ) | |
394 | { wxASSERT_MSG( GetKind() < wxT_SET, wxT("Illegal Kind for Base Type") ); } | |
395 | }; | |
396 | ||
397 | class WXDLLIMPEXP_BASE wxCustomTypeInfo : public wxTypeInfo | |
398 | { | |
399 | public: | |
400 | wxCustomTypeInfo( const wxString &name, wxVariant2StringFnc to, | |
401 | wxString2VariantFnc from ) : | |
402 | wxTypeInfo( wxT_CUSTOM, to, from, name ) | |
403 | {} | |
404 | }; | |
405 | ||
406 | class WXDLLIMPEXP_BASE wxEnumTypeInfo : public wxTypeInfo | |
407 | { | |
408 | public: | |
409 | typedef void (*converterToLong_t)( const wxAny& data, long &result ); | |
410 | typedef void (*converterFromLong_t)( long data, wxAny &result ); | |
411 | ||
412 | wxEnumTypeInfo( wxTypeKind kind, wxEnumData* enumInfo, wxVariant2StringFnc to, | |
413 | wxString2VariantFnc from, converterToLong_t toLong, | |
414 | converterFromLong_t fromLong, const wxString &name ) : | |
415 | wxTypeInfo( kind, to, from, name ), m_toLong( toLong ), m_fromLong( fromLong ) | |
416 | { | |
417 | wxASSERT_MSG( kind == wxT_ENUM || kind == wxT_SET, | |
418 | wxT("Illegal Kind for Enum Type")); | |
419 | m_enumInfo = enumInfo; | |
420 | } | |
421 | ||
422 | const wxEnumData* GetEnumData() const { return m_enumInfo; } | |
423 | ||
424 | // convert a wxAny holding data of this type into a long | |
425 | void ConvertToLong( const wxAny& data, long &result ) const | |
426 | { | |
427 | if( m_toLong ) | |
428 | (*m_toLong)( data, result ); | |
429 | else | |
430 | wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) ); | |
431 | } | |
432 | ||
433 | // convert a long into a wxAny holding the corresponding data in this type | |
434 | void ConvertFromLong( long data, wxAny &result ) const | |
435 | { | |
436 | if( m_fromLong ) | |
437 | (*m_fromLong)( data, result ); | |
438 | else | |
439 | wxLogError( wxGetTranslation(wxT("Long Conversions not supported")) ); | |
440 | } | |
441 | ||
442 | private: | |
443 | converterToLong_t m_toLong; | |
444 | converterFromLong_t m_fromLong; | |
445 | ||
446 | wxEnumData *m_enumInfo; // Kind == wxT_ENUM or Kind == wxT_SET | |
447 | }; | |
448 | ||
449 | class WXDLLIMPEXP_BASE wxClassTypeInfo : public wxTypeInfo | |
450 | { | |
451 | public: | |
452 | wxClassTypeInfo( wxTypeKind kind, wxClassInfo* classInfo, | |
453 | wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL, | |
454 | const wxString &name = wxEmptyString); | |
455 | ||
456 | const wxClassInfo *GetClassInfo() const { return m_classInfo; } | |
457 | ||
458 | private: | |
459 | wxClassInfo *m_classInfo; // Kind == wxT_OBJECT - could be NULL | |
460 | }; | |
461 | ||
462 | class WXDLLIMPEXP_BASE wxCollectionTypeInfo : public wxTypeInfo | |
463 | { | |
464 | public: | |
465 | wxCollectionTypeInfo( const wxString &elementName, wxVariant2StringFnc to, | |
466 | wxString2VariantFnc from , const wxString &name) : | |
467 | wxTypeInfo( wxT_COLLECTION, to, from, name ) | |
468 | { m_elementTypeName = elementName; m_elementType = NULL; } | |
469 | ||
470 | const wxTypeInfo* GetElementType() const | |
471 | { | |
472 | if ( m_elementType == NULL ) | |
473 | m_elementType = wxTypeInfo::FindType( m_elementTypeName ); | |
474 | return m_elementType; | |
475 | } | |
476 | ||
477 | private: | |
478 | mutable wxTypeInfo * m_elementType; | |
479 | wxString m_elementTypeName; | |
480 | }; | |
481 | ||
482 | class WXDLLIMPEXP_BASE wxEventSourceTypeInfo : public wxTypeInfo | |
483 | { | |
484 | public: | |
485 | wxEventSourceTypeInfo( int eventType, wxClassInfo* eventClass, | |
486 | wxVariant2StringFnc to = NULL, | |
487 | wxString2VariantFnc from = NULL ); | |
488 | wxEventSourceTypeInfo( int eventType, int lastEventType, wxClassInfo* eventClass, | |
489 | wxVariant2StringFnc to = NULL, wxString2VariantFnc from = NULL ); | |
490 | ||
491 | int GetEventType() const { return m_eventType; } | |
492 | int GetLastEventType() const { return m_lastEventType; } | |
493 | const wxClassInfo* GetEventClass() const { return m_eventClass; } | |
494 | ||
495 | private: | |
496 | const wxClassInfo *m_eventClass; // (extended will merge into classinfo) | |
497 | int m_eventType; | |
498 | int m_lastEventType; | |
499 | }; | |
500 | ||
501 | template<typename T> const wxTypeInfo* wxGetTypeInfo( T * ) | |
502 | { return wxTypeInfo::FindType(typeid(T).name()); } | |
503 | ||
504 | // this macro is for usage with custom, non-object derived classes and structs, | |
505 | // wxPoint is such a custom type | |
506 | ||
507 | #if wxUSE_FUNC_TEMPLATE_POINTER | |
508 | #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \ | |
509 | wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), &toString, &fromString); | |
510 | #else | |
511 | #define wxCUSTOM_TYPE_INFO( e, toString, fromString ) \ | |
512 | void ToString##e( const wxAny& data, wxString &result ) \ | |
513 | { toString(data, result); } \ | |
514 | void FromString##e( const wxString& data, wxAny &result ) \ | |
515 | { fromString(data, result); } \ | |
516 | wxCustomTypeInfo s_typeInfo##e(typeid(e).name(), \ | |
517 | &ToString##e, &FromString##e); | |
518 | #endif | |
519 | ||
520 | #define wxCOLLECTION_TYPE_INFO( element, collection ) \ | |
521 | wxCollectionTypeInfo s_typeInfo##collection( typeid(element).name(), \ | |
522 | NULL, NULL, typeid(collection).name() ); | |
523 | ||
524 | // sometimes a compiler invents specializations that are nowhere called, | |
525 | // use this macro to satisfy the refs, currently we don't have to play | |
526 | // tricks, but if we will have to according to the compiler, we will use | |
527 | // that macro for that | |
528 | ||
529 | #define wxILLEGAL_TYPE_SPECIALIZATION( a ) | |
530 | ||
531 | #endif // wxUSE_EXTENDED_RTTI | |
532 | #endif // _XTITYPES_H_ |