]>
Commit | Line | Data |
---|---|---|
39601a7f VZ |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: wx/any.h | |
3 | // Purpose: wxAny class | |
4 | // Author: Jaakko Salli | |
5 | // Modified by: | |
6 | // Created: 07/05/2009 | |
39601a7f VZ |
7 | // Copyright: (c) wxWidgets team |
8 | // Licence: wxWindows licence | |
9 | ///////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | #ifndef _WX_ANY_H_ | |
12 | #define _WX_ANY_H_ | |
13 | ||
14 | #include "wx/defs.h" | |
15 | ||
16 | #if wxUSE_ANY | |
17 | ||
94cd7b00 | 18 | #include <new> // for placement new |
39601a7f | 19 | #include "wx/string.h" |
39601a7f | 20 | #include "wx/meta/if.h" |
7db064f6 | 21 | #include "wx/typeinfo.h" |
f41d5991 | 22 | #include "wx/list.h" |
39601a7f VZ |
23 | |
24 | // Size of the wxAny value buffer. | |
25 | enum | |
26 | { | |
27 | WX_ANY_VALUE_BUFFER_SIZE = 16 | |
28 | }; | |
29 | ||
30 | union wxAnyValueBuffer | |
31 | { | |
ca5a3614 JS |
32 | union Alignment |
33 | { | |
34 | #if wxHAS_INT64 | |
35 | wxInt64 m_int64; | |
36 | #endif | |
37 | long double m_longDouble; | |
38 | void ( *m_funcPtr )(void); | |
39 | void ( wxAnyValueBuffer::*m_mFuncPtr )(void); | |
40 | } m_alignment; | |
41 | ||
39601a7f VZ |
42 | void* m_ptr; |
43 | wxByte m_buffer[WX_ANY_VALUE_BUFFER_SIZE]; | |
44 | }; | |
45 | ||
39601a7f VZ |
46 | // |
47 | // wxAnyValueType is base class for value type functionality for C++ data | |
48 | // types used with wxAny. Usually the default template (wxAnyValueTypeImpl<>) | |
49 | // will create a satisfactory wxAnyValueType implementation for a data type. | |
50 | // | |
51 | class WXDLLIMPEXP_BASE wxAnyValueType | |
52 | { | |
7db064f6 | 53 | WX_DECLARE_ABSTRACT_TYPEINFO(wxAnyValueType) |
39601a7f VZ |
54 | public: |
55 | /** | |
56 | Default constructor. | |
57 | */ | |
0cc226ad JS |
58 | wxAnyValueType() |
59 | { | |
60 | } | |
39601a7f VZ |
61 | |
62 | /** | |
63 | Destructor. | |
64 | */ | |
65 | virtual ~wxAnyValueType() | |
66 | { | |
67 | } | |
68 | ||
39601a7f VZ |
69 | /** |
70 | This function is used for internal type matching. | |
71 | */ | |
72 | virtual bool IsSameType(const wxAnyValueType* otherType) const = 0; | |
73 | ||
74 | /** | |
75 | This function is called every time the data in wxAny | |
76 | buffer needs to be freed. | |
77 | */ | |
78 | virtual void DeleteValue(wxAnyValueBuffer& buf) const = 0; | |
79 | ||
80 | /** | |
24985a9b JS |
81 | Implement this for buffer-to-buffer copy. |
82 | ||
83 | @param src | |
84 | This is the source data buffer. | |
85 | ||
86 | @param dst | |
87 | This is the destination data buffer that is in either | |
88 | uninitialized or freed state. | |
39601a7f VZ |
89 | */ |
90 | virtual void CopyBuffer(const wxAnyValueBuffer& src, | |
91 | wxAnyValueBuffer& dst) const = 0; | |
92 | ||
93 | /** | |
94 | Convert value into buffer of different type. Return false if | |
95 | not possible. | |
96 | */ | |
97 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
98 | wxAnyValueType* dstType, | |
99 | wxAnyValueBuffer& dst) const = 0; | |
100 | ||
101 | /** | |
102 | Use this template function for checking if wxAnyValueType represents | |
103 | a specific C++ data type. | |
104 | ||
105 | @remarks This template function does not work on some older compilers | |
f41d5991 | 106 | (such as Visual C++ 6.0). For full compiler compatibility |
39601a7f VZ |
107 | please use wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) macro |
108 | instead. | |
109 | ||
110 | @see wxAny::CheckType() | |
111 | */ | |
112 | // FIXME-VC6: remove this hack when VC6 is no longer supported | |
113 | template <typename T> | |
49ddcdf9 | 114 | bool CheckType(T* reserved = NULL) const; |
cbca59a8 SC |
115 | |
116 | #if wxUSE_EXTENDED_RTTI | |
117 | virtual const wxTypeInfo* GetTypeInfo() const = 0; | |
118 | #endif | |
39601a7f VZ |
119 | private: |
120 | }; | |
121 | ||
0cc226ad JS |
122 | |
123 | // | |
124 | // We need to allocate wxAnyValueType instances in heap, and need to use | |
125 | // scoped ptr to properly deallocate them in dynamic library use cases. | |
126 | // Here we have a minimal specialized scoped ptr implementation to deal | |
127 | // with various compiler-specific problems with template class' static | |
128 | // member variable of template type with explicit constructor which | |
129 | // is initialized in global scope. | |
130 | // | |
131 | class wxAnyValueTypeScopedPtr | |
132 | { | |
133 | public: | |
134 | wxAnyValueTypeScopedPtr(wxAnyValueType* ptr) : m_ptr(ptr) { } | |
135 | ~wxAnyValueTypeScopedPtr() { delete m_ptr; } | |
136 | wxAnyValueType* get() const { return m_ptr; } | |
137 | private: | |
138 | wxAnyValueType* m_ptr; | |
139 | }; | |
140 | ||
141 | ||
39601a7f VZ |
142 | // |
143 | // This method of checking the type is compatible with VC6 | |
144 | #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \ | |
145 | wxAnyValueTypeImpl<T>::IsSameClass(valueTypePtr) | |
146 | ||
39601a7f VZ |
147 | |
148 | /** | |
149 | Helper macro for defining user value types. | |
150 | ||
7db064f6 JS |
151 | Even though C++ RTTI would be fully available to use, we'd have to to |
152 | facilitate sub-type system which allows, for instance, wxAny with | |
153 | signed short '15' to be treated equal to wxAny with signed long long '15'. | |
154 | Having sm_instance is important here. | |
0cc226ad JS |
155 | |
156 | NB: We really need to have wxAnyValueType instances allocated | |
157 | in heap. They are stored as static template member variables, | |
158 | and with them we just can't be too careful (eg. not allocating | |
159 | them in heap broke the type identification in GCC). | |
39601a7f VZ |
160 | */ |
161 | #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \ | |
162 | friend class wxAny; \ | |
7db064f6 | 163 | WX_DECLARE_TYPEINFO_INLINE(CLS) \ |
39601a7f | 164 | public: \ |
39601a7f VZ |
165 | static bool IsSameClass(const wxAnyValueType* otherType) \ |
166 | { \ | |
0cc226ad | 167 | return wxTypeId(*sm_instance.get()) == wxTypeId(*otherType); \ |
39601a7f VZ |
168 | } \ |
169 | virtual bool IsSameType(const wxAnyValueType* otherType) const \ | |
170 | { \ | |
171 | return IsSameClass(otherType); \ | |
172 | } \ | |
173 | private: \ | |
0cc226ad | 174 | static wxAnyValueTypeScopedPtr sm_instance; \ |
39601a7f VZ |
175 | public: \ |
176 | static wxAnyValueType* GetInstance() \ | |
177 | { \ | |
0cc226ad | 178 | return sm_instance.get(); \ |
39601a7f VZ |
179 | } |
180 | ||
181 | ||
182 | #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \ | |
0cc226ad | 183 | wxAnyValueTypeScopedPtr CLS::sm_instance(new CLS()); |
39601a7f VZ |
184 | |
185 | ||
186 | #ifdef __VISUALC6__ | |
187 | // "non dll-interface class 'xxx' used as base interface | |
188 | #pragma warning (push) | |
189 | #pragma warning (disable:4275) | |
190 | #endif | |
191 | ||
192 | /** | |
193 | Following are helper classes for the wxAnyValueTypeImplBase. | |
194 | */ | |
195 | namespace wxPrivate | |
196 | { | |
197 | ||
198 | template<typename T> | |
94cd7b00 | 199 | class wxAnyValueTypeOpsInplace |
39601a7f VZ |
200 | { |
201 | public: | |
202 | static void DeleteValue(wxAnyValueBuffer& buf) | |
203 | { | |
94cd7b00 JS |
204 | T* value = reinterpret_cast<T*>(&buf.m_buffer[0]); |
205 | value->~T(); | |
206 | ||
207 | // Some compiler may given 'unused variable' warnings without this | |
208 | wxUnusedVar(value); | |
39601a7f VZ |
209 | } |
210 | ||
211 | static void SetValue(const T& value, | |
212 | wxAnyValueBuffer& buf) | |
213 | { | |
94cd7b00 JS |
214 | // Use placement new |
215 | void* const place = buf.m_buffer; | |
216 | ::new(place) T(value); | |
39601a7f VZ |
217 | } |
218 | ||
219 | static const T& GetValue(const wxAnyValueBuffer& buf) | |
220 | { | |
f41d5991 | 221 | // Breaking this code into two lines should suppress |
1237a25b JS |
222 | // GCC's 'type-punned pointer will break strict-aliasing rules' |
223 | // warning. | |
224 | const T* value = reinterpret_cast<const T*>(&buf.m_buffer[0]); | |
225 | return *value; | |
39601a7f VZ |
226 | } |
227 | }; | |
228 | ||
229 | ||
230 | template<typename T> | |
231 | class wxAnyValueTypeOpsGeneric | |
232 | { | |
233 | public: | |
234 | template<typename T2> | |
235 | class DataHolder | |
236 | { | |
237 | public: | |
238 | DataHolder(const T2& value) | |
239 | { | |
240 | m_value = value; | |
241 | } | |
242 | virtual ~DataHolder() { } | |
243 | ||
244 | T2 m_value; | |
245 | private: | |
246 | wxDECLARE_NO_COPY_CLASS(DataHolder); | |
247 | }; | |
248 | ||
249 | static void DeleteValue(wxAnyValueBuffer& buf) | |
250 | { | |
251 | DataHolder<T>* holder = static_cast<DataHolder<T>*>(buf.m_ptr); | |
252 | delete holder; | |
253 | } | |
254 | ||
255 | static void SetValue(const T& value, | |
256 | wxAnyValueBuffer& buf) | |
257 | { | |
258 | DataHolder<T>* holder = new DataHolder<T>(value); | |
259 | buf.m_ptr = holder; | |
260 | } | |
261 | ||
262 | static const T& GetValue(const wxAnyValueBuffer& buf) | |
263 | { | |
264 | DataHolder<T>* holder = static_cast<DataHolder<T>*>(buf.m_ptr); | |
265 | return holder->m_value; | |
266 | } | |
267 | }; | |
268 | ||
269 | } // namespace wxPrivate | |
270 | ||
271 | ||
272 | /** | |
273 | Intermediate template for the generic value type implementation. | |
274 | We can derive from this same value type for multiple actual types | |
275 | (for instance, we can have wxAnyValueTypeImplInt for all signed | |
276 | integer types), and also easily implement specialized templates | |
277 | with specific dynamic type conversion. | |
278 | */ | |
279 | template<typename T> | |
280 | class wxAnyValueTypeImplBase : public wxAnyValueType | |
281 | { | |
94cd7b00 JS |
282 | typedef typename wxIf< sizeof(T) <= WX_ANY_VALUE_BUFFER_SIZE, |
283 | wxPrivate::wxAnyValueTypeOpsInplace<T>, | |
39601a7f VZ |
284 | wxPrivate::wxAnyValueTypeOpsGeneric<T> >::value |
285 | Ops; | |
286 | ||
287 | public: | |
288 | wxAnyValueTypeImplBase() : wxAnyValueType() { } | |
289 | virtual ~wxAnyValueTypeImplBase() { } | |
290 | ||
291 | virtual void DeleteValue(wxAnyValueBuffer& buf) const | |
292 | { | |
293 | Ops::DeleteValue(buf); | |
39601a7f VZ |
294 | } |
295 | ||
296 | virtual void CopyBuffer(const wxAnyValueBuffer& src, | |
297 | wxAnyValueBuffer& dst) const | |
298 | { | |
39601a7f VZ |
299 | Ops::SetValue(Ops::GetValue(src), dst); |
300 | } | |
301 | ||
302 | /** | |
303 | It is important to reimplement this in any specialized template | |
304 | classes that inherit from wxAnyValueTypeImplBase. | |
305 | */ | |
306 | static void SetValue(const T& value, | |
307 | wxAnyValueBuffer& buf) | |
308 | { | |
309 | Ops::SetValue(value, buf); | |
310 | } | |
311 | ||
312 | /** | |
313 | It is important to reimplement this in any specialized template | |
314 | classes that inherit from wxAnyValueTypeImplBase. | |
315 | */ | |
316 | static const T& GetValue(const wxAnyValueBuffer& buf) | |
317 | { | |
318 | return Ops::GetValue(buf); | |
319 | } | |
cbca59a8 SC |
320 | #if wxUSE_EXTENDED_RTTI |
321 | virtual const wxTypeInfo* GetTypeInfo() const | |
322 | { | |
323 | return wxGetTypeInfo((T*)NULL); | |
324 | } | |
325 | #endif | |
39601a7f VZ |
326 | }; |
327 | ||
328 | ||
329 | /* | |
330 | Generic value type template. Note that bulk of the implementation | |
331 | resides in wxAnyValueTypeImplBase. | |
332 | */ | |
333 | template<typename T> | |
334 | class wxAnyValueTypeImpl : public wxAnyValueTypeImplBase<T> | |
335 | { | |
336 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<T>) | |
337 | public: | |
338 | wxAnyValueTypeImpl() : wxAnyValueTypeImplBase<T>() { } | |
339 | virtual ~wxAnyValueTypeImpl() { } | |
340 | ||
341 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
342 | wxAnyValueType* dstType, | |
343 | wxAnyValueBuffer& dst) const | |
344 | { | |
345 | wxUnusedVar(src); | |
346 | wxUnusedVar(dstType); | |
347 | wxUnusedVar(dst); | |
348 | return false; | |
349 | } | |
350 | }; | |
351 | ||
352 | template<typename T> | |
0cc226ad | 353 | wxAnyValueTypeScopedPtr wxAnyValueTypeImpl<T>::sm_instance = new wxAnyValueTypeImpl<T>(); |
39601a7f VZ |
354 | |
355 | ||
356 | // | |
357 | // Helper macro for using same base value type implementation for multiple | |
358 | // actual C++ data types. | |
359 | // | |
cbca59a8 | 360 | #define _WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \ |
39601a7f VZ |
361 | template<> \ |
362 | class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##CLSTYPE \ | |
363 | { \ | |
364 | typedef wxAnyBase##CLSTYPE##Type UseDataType; \ | |
365 | public: \ | |
366 | wxAnyValueTypeImpl() : wxAnyValueTypeImpl##CLSTYPE() { } \ | |
367 | virtual ~wxAnyValueTypeImpl() { } \ | |
368 | static void SetValue(const T& value, wxAnyValueBuffer& buf) \ | |
369 | { \ | |
1237a25b JS |
370 | void* voidPtr = reinterpret_cast<void*>(&buf.m_buffer[0]); \ |
371 | UseDataType* dptr = reinterpret_cast<UseDataType*>(voidPtr); \ | |
372 | *dptr = static_cast<UseDataType>(value); \ | |
39601a7f VZ |
373 | } \ |
374 | static T GetValue(const wxAnyValueBuffer& buf) \ | |
375 | { \ | |
1237a25b JS |
376 | const void* voidPtr = \ |
377 | reinterpret_cast<const void*>(&buf.m_buffer[0]); \ | |
378 | const UseDataType* sptr = \ | |
379 | reinterpret_cast<const UseDataType*>(voidPtr); \ | |
380 | return static_cast<T>(*sptr); \ | |
cbca59a8 SC |
381 | } |
382 | ||
383 | #if wxUSE_EXTENDED_RTTI | |
384 | #define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \ | |
385 | _WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE)\ | |
386 | virtual const wxTypeInfo* GetTypeInfo() const \ | |
387 | { \ | |
388 | return wxGetTypeInfo((T*)NULL); \ | |
39601a7f VZ |
389 | } \ |
390 | }; | |
cbca59a8 SC |
391 | #else |
392 | #define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \ | |
393 | _WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE)\ | |
394 | }; | |
395 | #endif | |
39601a7f VZ |
396 | |
397 | // | |
398 | // Integer value types | |
399 | // | |
400 | ||
401 | #ifdef wxLongLong_t | |
402 | typedef wxLongLong_t wxAnyBaseIntType; | |
403 | typedef wxULongLong_t wxAnyBaseUintType; | |
404 | #else | |
405 | typedef long wxAnyBaseIntType; | |
406 | typedef unsigned long wxAnyBaseUintType; | |
407 | #endif | |
408 | ||
409 | ||
410 | class WXDLLIMPEXP_BASE wxAnyValueTypeImplInt : | |
411 | public wxAnyValueTypeImplBase<wxAnyBaseIntType> | |
412 | { | |
413 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplInt) | |
414 | public: | |
415 | wxAnyValueTypeImplInt() : | |
416 | wxAnyValueTypeImplBase<wxAnyBaseIntType>() { } | |
417 | virtual ~wxAnyValueTypeImplInt() { } | |
418 | ||
419 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
420 | wxAnyValueType* dstType, | |
421 | wxAnyValueBuffer& dst) const; | |
422 | }; | |
423 | ||
424 | ||
425 | class WXDLLIMPEXP_BASE wxAnyValueTypeImplUint : | |
426 | public wxAnyValueTypeImplBase<wxAnyBaseUintType> | |
427 | { | |
428 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplUint) | |
429 | public: | |
430 | wxAnyValueTypeImplUint() : | |
431 | wxAnyValueTypeImplBase<wxAnyBaseUintType>() { } | |
432 | virtual ~wxAnyValueTypeImplUint() { } | |
433 | ||
434 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
435 | wxAnyValueType* dstType, | |
436 | wxAnyValueBuffer& dst) const; | |
437 | }; | |
438 | ||
439 | ||
440 | WX_ANY_DEFINE_SUB_TYPE(signed long, Int) | |
441 | WX_ANY_DEFINE_SUB_TYPE(signed int, Int) | |
442 | WX_ANY_DEFINE_SUB_TYPE(signed short, Int) | |
443 | WX_ANY_DEFINE_SUB_TYPE(signed char, Int) | |
444 | #ifdef wxLongLong_t | |
445 | WX_ANY_DEFINE_SUB_TYPE(wxLongLong_t, Int) | |
446 | #endif | |
447 | ||
448 | WX_ANY_DEFINE_SUB_TYPE(unsigned long, Uint) | |
449 | WX_ANY_DEFINE_SUB_TYPE(unsigned int, Uint) | |
450 | WX_ANY_DEFINE_SUB_TYPE(unsigned short, Uint) | |
451 | WX_ANY_DEFINE_SUB_TYPE(unsigned char, Uint) | |
452 | #ifdef wxLongLong_t | |
453 | WX_ANY_DEFINE_SUB_TYPE(wxULongLong_t, Uint) | |
454 | #endif | |
455 | ||
456 | ||
457 | // | |
153107b4 JS |
458 | // This macro is used in header, but then in source file we must have: |
459 | // WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl##TYPENAME) | |
39601a7f | 460 | // |
153107b4 JS |
461 | #define _WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, CONVFUNC, GV) \ |
462 | class WXDLLIMPEXP_BASE wxAnyValueTypeImpl##TYPENAME : \ | |
463 | public wxAnyValueTypeImplBase<T> \ | |
464 | { \ | |
465 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl##TYPENAME) \ | |
466 | public: \ | |
467 | wxAnyValueTypeImpl##TYPENAME() : \ | |
468 | wxAnyValueTypeImplBase<T>() { } \ | |
469 | virtual ~wxAnyValueTypeImpl##TYPENAME() { } \ | |
470 | virtual bool ConvertValue(const wxAnyValueBuffer& src, \ | |
471 | wxAnyValueType* dstType, \ | |
472 | wxAnyValueBuffer& dst) const \ | |
473 | { \ | |
474 | GV value = GetValue(src); \ | |
475 | return CONVFUNC(value, dstType, dst); \ | |
476 | } \ | |
477 | }; \ | |
478 | template<> \ | |
479 | class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##TYPENAME \ | |
480 | { \ | |
481 | public: \ | |
482 | wxAnyValueTypeImpl() : wxAnyValueTypeImpl##TYPENAME() { } \ | |
483 | virtual ~wxAnyValueTypeImpl() { } \ | |
484 | }; | |
39601a7f | 485 | |
153107b4 JS |
486 | #define WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, CONVFUNC, BT) \ |
487 | _WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, CONVFUNC, BT) \ | |
39601a7f | 488 | |
153107b4 JS |
489 | #define WX_ANY_DEFINE_CONVERTIBLE_TYPE_BASE(T, TYPENAME, CONVFUNC) \ |
490 | _WX_ANY_DEFINE_CONVERTIBLE_TYPE(T, TYPENAME, \ | |
491 | CONVFUNC, const T&) \ | |
39601a7f | 492 | |
153107b4 JS |
493 | // |
494 | // String value type | |
495 | // | |
39601a7f | 496 | |
153107b4 JS |
497 | // Convert wxString to destination wxAny value type |
498 | extern WXDLLIMPEXP_BASE bool wxAnyConvertString(const wxString& value, | |
499 | wxAnyValueType* dstType, | |
500 | wxAnyValueBuffer& dst); | |
501 | ||
502 | WX_ANY_DEFINE_CONVERTIBLE_TYPE_BASE(wxString, wxString, wxAnyConvertString) | |
503 | WX_ANY_DEFINE_CONVERTIBLE_TYPE(const char*, ConstCharPtr, | |
504 | wxAnyConvertString, wxString) | |
505 | WX_ANY_DEFINE_CONVERTIBLE_TYPE(const wchar_t*, ConstWchar_tPtr, | |
506 | wxAnyConvertString, wxString) | |
39601a7f VZ |
507 | |
508 | // | |
509 | // Bool value type | |
510 | // | |
511 | template<> | |
512 | class WXDLLIMPEXP_BASE wxAnyValueTypeImpl<bool> : | |
513 | public wxAnyValueTypeImplBase<bool> | |
514 | { | |
515 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>) | |
516 | public: | |
517 | wxAnyValueTypeImpl() : | |
518 | wxAnyValueTypeImplBase<bool>() { } | |
519 | virtual ~wxAnyValueTypeImpl() { } | |
520 | ||
521 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
522 | wxAnyValueType* dstType, | |
523 | wxAnyValueBuffer& dst) const; | |
524 | }; | |
525 | ||
526 | // | |
527 | // Floating point value type | |
528 | // | |
529 | class WXDLLIMPEXP_BASE wxAnyValueTypeImplDouble : | |
530 | public wxAnyValueTypeImplBase<double> | |
531 | { | |
532 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble) | |
533 | public: | |
534 | wxAnyValueTypeImplDouble() : | |
535 | wxAnyValueTypeImplBase<double>() { } | |
536 | virtual ~wxAnyValueTypeImplDouble() { } | |
537 | ||
538 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
539 | wxAnyValueType* dstType, | |
540 | wxAnyValueBuffer& dst) const; | |
541 | }; | |
542 | ||
543 | // WX_ANY_DEFINE_SUB_TYPE requires this | |
544 | typedef double wxAnyBaseDoubleType; | |
545 | ||
546 | WX_ANY_DEFINE_SUB_TYPE(float, Double) | |
547 | WX_ANY_DEFINE_SUB_TYPE(double, Double) | |
548 | ||
549 | ||
c5fe6a5b JS |
550 | // |
551 | // Defines a dummy wxAnyValueTypeImpl<> with given export | |
552 | // declaration. This is needed if a class is used with | |
553 | // wxAny in both user shared library and application. | |
554 | // | |
555 | #define wxDECLARE_ANY_TYPE(CLS, DECL) \ | |
556 | template<> \ | |
557 | class DECL wxAnyValueTypeImpl<CLS> : \ | |
558 | public wxAnyValueTypeImplBase<CLS> \ | |
559 | { \ | |
560 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<CLS>) \ | |
561 | public: \ | |
562 | wxAnyValueTypeImpl() : \ | |
563 | wxAnyValueTypeImplBase<CLS>() { } \ | |
564 | virtual ~wxAnyValueTypeImpl() { } \ | |
565 | \ | |
566 | virtual bool ConvertValue(const wxAnyValueBuffer& src, \ | |
567 | wxAnyValueType* dstType, \ | |
568 | wxAnyValueBuffer& dst) const \ | |
569 | { \ | |
570 | wxUnusedVar(src); \ | |
571 | wxUnusedVar(dstType); \ | |
572 | wxUnusedVar(dst); \ | |
573 | return false; \ | |
574 | } \ | |
575 | }; | |
576 | ||
577 | ||
578 | // Make sure some of wx's own types get the right wxAnyValueType export | |
579 | // (this is needed only for types that are referred to from wxBase. | |
580 | // currently we may not use any of these types from there, but let's | |
581 | // use the macro on at least one to make sure it compiles since we can't | |
f41d5991 | 582 | // really test it properly in unit tests since a separate DLL would |
c5fe6a5b JS |
583 | // be needed). |
584 | #if wxUSE_DATETIME | |
585 | #include "wx/datetime.h" | |
586 | wxDECLARE_ANY_TYPE(wxDateTime, WXDLLIMPEXP_BASE) | |
587 | #endif | |
588 | ||
589 | //#include "wx/object.h" | |
590 | //wxDECLARE_ANY_TYPE(wxObject*, WXDLLIMPEXP_BASE) | |
591 | ||
592 | //#include "wx/arrstr.h" | |
593 | //wxDECLARE_ANY_TYPE(wxArrayString, WXDLLIMPEXP_BASE) | |
594 | ||
595 | ||
0bf14ab8 JS |
596 | #if wxUSE_VARIANT |
597 | ||
598 | class WXDLLIMPEXP_FWD_BASE wxAnyToVariantRegistration; | |
599 | ||
600 | // Because of header inter-dependencies, cannot include this earlier | |
601 | #include "wx/variant.h" | |
602 | ||
603 | // | |
604 | // wxVariantData* data type implementation. For cases when appropriate | |
605 | // wxAny<->wxVariant conversion code is missing. | |
606 | // | |
607 | ||
608 | class WXDLLIMPEXP_BASE wxAnyValueTypeImplVariantData : | |
609 | public wxAnyValueTypeImplBase<wxVariantData*> | |
610 | { | |
611 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData) | |
612 | public: | |
613 | wxAnyValueTypeImplVariantData() : | |
614 | wxAnyValueTypeImplBase<wxVariantData*>() { } | |
615 | virtual ~wxAnyValueTypeImplVariantData() { } | |
616 | ||
617 | virtual void DeleteValue(wxAnyValueBuffer& buf) const | |
618 | { | |
619 | wxVariantData* data = static_cast<wxVariantData*>(buf.m_ptr); | |
620 | if ( data ) | |
621 | data->DecRef(); | |
622 | } | |
623 | ||
624 | virtual void CopyBuffer(const wxAnyValueBuffer& src, | |
625 | wxAnyValueBuffer& dst) const | |
626 | { | |
627 | wxVariantData* data = static_cast<wxVariantData*>(src.m_ptr); | |
628 | if ( data ) | |
629 | data->IncRef(); | |
630 | dst.m_ptr = data; | |
631 | } | |
632 | ||
633 | static void SetValue(wxVariantData* value, | |
634 | wxAnyValueBuffer& buf) | |
635 | { | |
636 | value->IncRef(); | |
637 | buf.m_ptr = value; | |
638 | } | |
639 | ||
640 | static wxVariantData* GetValue(const wxAnyValueBuffer& buf) | |
641 | { | |
642 | return static_cast<wxVariantData*>(buf.m_ptr); | |
643 | } | |
644 | ||
645 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
646 | wxAnyValueType* dstType, | |
647 | wxAnyValueBuffer& dst) const | |
648 | { | |
649 | wxUnusedVar(src); | |
650 | wxUnusedVar(dstType); | |
651 | wxUnusedVar(dst); | |
652 | return false; | |
653 | } | |
654 | }; | |
655 | ||
656 | template<> | |
657 | class wxAnyValueTypeImpl<wxVariantData*> : | |
658 | public wxAnyValueTypeImplVariantData | |
659 | { | |
660 | public: | |
661 | wxAnyValueTypeImpl() : wxAnyValueTypeImplVariantData() { } | |
662 | virtual ~wxAnyValueTypeImpl() { } | |
663 | }; | |
664 | ||
665 | #endif // wxUSE_VARIANT | |
c5fe6a5b | 666 | |
39601a7f VZ |
667 | #ifdef __VISUALC6__ |
668 | // Re-enable useless VC6 warnings | |
669 | #pragma warning (pop) | |
670 | #endif | |
671 | ||
672 | ||
673 | /* | |
674 | Let's define a discrete Null value so we don't have to really | |
675 | ever check if wxAny.m_type pointer is NULL or not. This is an | |
676 | optimization, mostly. Implementation of this value type is | |
677 | "hidden" in the source file. | |
678 | */ | |
679 | extern WXDLLIMPEXP_DATA_BASE(wxAnyValueType*) wxAnyNullValueType; | |
680 | ||
681 | ||
682 | // | |
683 | // We need to implement custom signed/unsigned int equals operators | |
684 | // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work. | |
685 | #define WXANY_IMPLEMENT_INT_EQ_OP(TS, TUS) \ | |
686 | bool operator==(TS value) const \ | |
687 | { \ | |
688 | if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \ | |
689 | return (value == static_cast<TS> \ | |
690 | (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \ | |
691 | if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \ | |
692 | return (value == static_cast<TS> \ | |
693 | (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \ | |
694 | return false; \ | |
695 | } \ | |
696 | bool operator==(TUS value) const \ | |
697 | { \ | |
698 | if ( wxAnyValueTypeImpl<TUS>::IsSameClass(m_type) ) \ | |
699 | return (value == static_cast<TUS> \ | |
700 | (wxAnyValueTypeImpl<TUS>::GetValue(m_buffer))); \ | |
701 | if ( wxAnyValueTypeImpl<TS>::IsSameClass(m_type) ) \ | |
702 | return (value == static_cast<TUS> \ | |
703 | (wxAnyValueTypeImpl<TS>::GetValue(m_buffer))); \ | |
704 | return false; \ | |
705 | } | |
706 | ||
707 | ||
0bf14ab8 JS |
708 | #if wxUSE_VARIANT |
709 | ||
710 | // Note that the following functions are implemented outside wxAny class | |
711 | // so that it can reside entirely in header and lack the export declaration. | |
712 | ||
713 | // Helper function used to associate wxAnyValueType with a wxVariantData. | |
714 | extern WXDLLIMPEXP_BASE void | |
715 | wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg); | |
716 | ||
717 | // This function performs main wxAny to wxVariant conversion duties. | |
718 | extern WXDLLIMPEXP_BASE bool | |
719 | wxConvertAnyToVariant(const wxAny& any, wxVariant* variant); | |
720 | ||
721 | #endif // wxUSE_VARIANT | |
722 | ||
723 | ||
39601a7f VZ |
724 | // |
725 | // The wxAny class represents a container for any type. A variant's value | |
726 | // can be changed at run time, possibly to a different type of value. | |
727 | // | |
728 | // As standard, wxAny can store value of almost any type, in a fairly | |
729 | // optimal manner even. | |
730 | // | |
45de347c | 731 | class wxAny |
39601a7f VZ |
732 | { |
733 | public: | |
734 | /** | |
735 | Default constructor. | |
736 | */ | |
737 | wxAny() | |
738 | { | |
739 | m_type = wxAnyNullValueType; | |
740 | } | |
741 | ||
742 | /** | |
743 | Destructor. | |
744 | */ | |
745 | ~wxAny() | |
746 | { | |
747 | m_type->DeleteValue(m_buffer); | |
748 | } | |
749 | ||
750 | //@{ | |
751 | /** | |
752 | Various constructors. | |
753 | */ | |
ea412ac4 JS |
754 | template<typename T> |
755 | wxAny(const T& value) | |
756 | { | |
0cc226ad | 757 | m_type = wxAnyValueTypeImpl<T>::sm_instance.get(); |
ea412ac4 JS |
758 | wxAnyValueTypeImpl<T>::SetValue(value, m_buffer); |
759 | } | |
760 | ||
153107b4 | 761 | // These two constructors are needed to deal with string literals |
39601a7f VZ |
762 | wxAny(const char* value) |
763 | { | |
0cc226ad | 764 | m_type = wxAnyValueTypeImpl<const char*>::sm_instance.get(); |
153107b4 | 765 | wxAnyValueTypeImpl<const char*>::SetValue(value, m_buffer); |
39601a7f VZ |
766 | } |
767 | wxAny(const wchar_t* value) | |
768 | { | |
0cc226ad | 769 | m_type = wxAnyValueTypeImpl<const wchar_t*>::sm_instance.get(); |
153107b4 | 770 | wxAnyValueTypeImpl<const wchar_t*>::SetValue(value, m_buffer); |
39601a7f VZ |
771 | } |
772 | ||
773 | wxAny(const wxAny& any) | |
774 | { | |
775 | m_type = wxAnyNullValueType; | |
776 | AssignAny(any); | |
777 | } | |
778 | ||
0bf14ab8 JS |
779 | #if wxUSE_VARIANT |
780 | wxAny(const wxVariant& variant) | |
781 | { | |
782 | m_type = wxAnyNullValueType; | |
783 | AssignVariant(variant); | |
784 | } | |
785 | #endif | |
786 | ||
39601a7f VZ |
787 | //@} |
788 | ||
789 | /** | |
790 | Use this template function for checking if this wxAny holds | |
791 | a specific C++ data type. | |
792 | ||
793 | @remarks This template function does not work on some older compilers | |
794 | (such as Visual C++ 6.0). For full compiler ccompatibility | |
795 | please use wxANY_CHECK_TYPE(any, T) macro instead. | |
796 | ||
797 | @see wxAnyValueType::CheckType() | |
798 | */ | |
799 | // FIXME-VC6: remove this hack when VC6 is no longer supported | |
800 | template <typename T> | |
49ddcdf9 | 801 | bool CheckType(T* = NULL) const |
39601a7f VZ |
802 | { |
803 | return m_type->CheckType<T>(); | |
804 | } | |
805 | ||
806 | /** | |
807 | Returns the value type as wxAnyValueType instance. | |
808 | ||
809 | @remarks You cannot reliably test whether two wxAnys are of | |
810 | same value type by simply comparing return values | |
f1156cbb JS |
811 | of wxAny::GetType(). Instead, use wxAny::HasSameType(). |
812 | ||
813 | @see HasSameType() | |
39601a7f VZ |
814 | */ |
815 | const wxAnyValueType* GetType() const | |
816 | { | |
817 | return m_type; | |
818 | } | |
819 | ||
f1156cbb JS |
820 | /** |
821 | Returns @true if this and another wxAny have the same | |
822 | value type. | |
823 | */ | |
824 | bool HasSameType(const wxAny& other) const | |
825 | { | |
826 | return GetType()->IsSameType(other.GetType()); | |
827 | } | |
828 | ||
39601a7f | 829 | /** |
79c60a3e | 830 | Tests if wxAny is null (that is, whether there is no data). |
39601a7f VZ |
831 | */ |
832 | bool IsNull() const | |
833 | { | |
834 | return (m_type == wxAnyNullValueType); | |
835 | } | |
836 | ||
837 | /** | |
838 | Makes wxAny null (that is, clears it). | |
839 | */ | |
840 | void MakeNull() | |
841 | { | |
842 | m_type->DeleteValue(m_buffer); | |
843 | m_type = wxAnyNullValueType; | |
844 | } | |
845 | ||
846 | //@{ | |
847 | /** | |
848 | Assignment operators. | |
849 | */ | |
49efebe2 JS |
850 | template<typename T> |
851 | wxAny& operator=(const T &value) | |
852 | { | |
853 | m_type->DeleteValue(m_buffer); | |
0cc226ad | 854 | m_type = wxAnyValueTypeImpl<T>::sm_instance.get(); |
49efebe2 JS |
855 | wxAnyValueTypeImpl<T>::SetValue(value, m_buffer); |
856 | return *this; | |
857 | } | |
858 | ||
39601a7f VZ |
859 | wxAny& operator=(const wxAny &any) |
860 | { | |
2a32b807 PC |
861 | if (this != &any) |
862 | AssignAny(any); | |
39601a7f VZ |
863 | return *this; |
864 | } | |
865 | ||
49efebe2 | 866 | #if wxUSE_VARIANT |
0bf14ab8 JS |
867 | wxAny& operator=(const wxVariant &variant) |
868 | { | |
869 | AssignVariant(variant); | |
870 | return *this; | |
871 | } | |
872 | #endif | |
873 | ||
153107b4 | 874 | // These two operators are needed to deal with string literals |
39601a7f | 875 | wxAny& operator=(const char* value) |
153107b4 JS |
876 | { |
877 | Assign(value); | |
878 | return *this; | |
879 | } | |
39601a7f | 880 | wxAny& operator=(const wchar_t* value) |
153107b4 JS |
881 | { |
882 | Assign(value); | |
883 | return *this; | |
884 | } | |
39601a7f VZ |
885 | |
886 | //@{ | |
887 | /** | |
888 | Equality operators. | |
889 | */ | |
890 | bool operator==(const wxString& value) const | |
891 | { | |
153107b4 JS |
892 | wxString value2; |
893 | if ( !GetAs(&value2) ) | |
39601a7f | 894 | return false; |
153107b4 | 895 | return value == value2; |
39601a7f VZ |
896 | } |
897 | ||
898 | bool operator==(const char* value) const | |
899 | { return (*this) == wxString(value); } | |
900 | bool operator==(const wchar_t* value) const | |
901 | { return (*this) == wxString(value); } | |
902 | ||
903 | // | |
904 | // We need to implement custom signed/unsigned int equals operators | |
905 | // for signed/unsigned (eg. wxAny(128UL) == 128L) comparisons to work. | |
906 | WXANY_IMPLEMENT_INT_EQ_OP(signed char, unsigned char) | |
907 | WXANY_IMPLEMENT_INT_EQ_OP(signed short, unsigned short) | |
908 | WXANY_IMPLEMENT_INT_EQ_OP(signed int, unsigned int) | |
909 | WXANY_IMPLEMENT_INT_EQ_OP(signed long, unsigned long) | |
910 | #ifdef wxLongLong_t | |
911 | WXANY_IMPLEMENT_INT_EQ_OP(wxLongLong_t, wxULongLong_t) | |
912 | #endif | |
913 | ||
33f9dbda VZ |
914 | wxGCC_WARNING_SUPPRESS(float-equal) |
915 | ||
39601a7f VZ |
916 | bool operator==(float value) const |
917 | { | |
918 | if ( !wxAnyValueTypeImpl<float>::IsSameClass(m_type) ) | |
919 | return false; | |
920 | ||
921 | return value == | |
922 | static_cast<float> | |
923 | (wxAnyValueTypeImpl<float>::GetValue(m_buffer)); | |
924 | } | |
925 | ||
926 | bool operator==(double value) const | |
927 | { | |
928 | if ( !wxAnyValueTypeImpl<double>::IsSameClass(m_type) ) | |
929 | return false; | |
930 | ||
931 | return value == | |
932 | static_cast<double> | |
933 | (wxAnyValueTypeImpl<double>::GetValue(m_buffer)); | |
934 | } | |
935 | ||
33f9dbda VZ |
936 | wxGCC_WARNING_RESTORE(float-equal) |
937 | ||
39601a7f VZ |
938 | bool operator==(bool value) const |
939 | { | |
940 | if ( !wxAnyValueTypeImpl<bool>::IsSameClass(m_type) ) | |
941 | return false; | |
942 | ||
943 | return value == (wxAnyValueTypeImpl<bool>::GetValue(m_buffer)); | |
944 | } | |
945 | ||
946 | //@} | |
947 | ||
948 | //@{ | |
949 | /** | |
950 | Inequality operators (implement as template). | |
951 | */ | |
952 | template<typename T> | |
953 | bool operator!=(const T& value) const | |
954 | { return !((*this) == value); } | |
955 | //@} | |
956 | ||
957 | /** | |
153107b4 JS |
958 | This template function converts wxAny into given type. In most cases |
959 | no type conversion is performed, so if the type is incorrect an | |
960 | assertion failure will occur. | |
39601a7f | 961 | |
f41d5991 | 962 | @remarks For convenience, conversion is done when T is wxString. This |
153107b4 JS |
963 | is useful when a string literal (which are treated as |
964 | const char* and const wchar_t*) has been assigned to wxAny. | |
965 | ||
966 | This template function may not work properly with Visual C++ | |
967 | 6. For full compiler compatibility, please use | |
968 | wxANY_AS(any, T) macro instead. | |
39601a7f VZ |
969 | */ |
970 | // FIXME-VC6: remove this hack when VC6 is no longer supported | |
971 | template<typename T> | |
972 | T As(T* = NULL) const | |
973 | { | |
974 | if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) ) | |
01937278 | 975 | { |
39601a7f | 976 | wxFAIL_MSG("Incorrect or non-convertible data type"); |
01937278 VZ |
977 | } |
978 | ||
39601a7f VZ |
979 | return static_cast<T>(wxAnyValueTypeImpl<T>::GetValue(m_buffer)); |
980 | } | |
981 | ||
153107b4 JS |
982 | // Allow easy conversion from 'const char *' etc. to wxString |
983 | // FIXME-VC6: remove this hack when VC6 is no longer supported | |
984 | //template<> | |
985 | wxString As(wxString*) const | |
986 | { | |
987 | wxString value; | |
988 | if ( !GetAs(&value) ) | |
989 | { | |
990 | wxFAIL_MSG("Incorrect or non-convertible data type"); | |
991 | } | |
992 | return value; | |
993 | } | |
994 | ||
cbca59a8 SC |
995 | #if wxUSE_EXTENDED_RTTI |
996 | const wxTypeInfo* GetTypeInfo() const | |
997 | { | |
998 | return m_type->GetTypeInfo(); | |
999 | } | |
1000 | #endif | |
39601a7f | 1001 | /** |
f41d5991 | 1002 | Template function that retrieves and converts the value of this |
39601a7f VZ |
1003 | variant to the type that T* value is. |
1004 | ||
f41d5991 | 1005 | @return Returns @true if conversion was successful. |
39601a7f VZ |
1006 | */ |
1007 | template<typename T> | |
1008 | bool GetAs(T* value) const | |
1009 | { | |
1010 | if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) ) | |
1011 | { | |
1012 | wxAnyValueType* otherType = | |
0cc226ad | 1013 | wxAnyValueTypeImpl<T>::sm_instance.get(); |
39601a7f VZ |
1014 | wxAnyValueBuffer temp_buf; |
1015 | ||
1016 | if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) ) | |
1017 | return false; | |
1018 | ||
1019 | *value = | |
1020 | static_cast<T>(wxAnyValueTypeImpl<T>::GetValue(temp_buf)); | |
1021 | otherType->DeleteValue(temp_buf); | |
1022 | ||
1023 | return true; | |
1024 | } | |
1025 | *value = static_cast<T>(wxAnyValueTypeImpl<T>::GetValue(m_buffer)); | |
1026 | return true; | |
1027 | } | |
1028 | ||
0bf14ab8 JS |
1029 | #if wxUSE_VARIANT |
1030 | // GetAs() wxVariant specialization | |
1031 | bool GetAs(wxVariant* value) const | |
1032 | { | |
1033 | return wxConvertAnyToVariant(*this, value); | |
1034 | } | |
1035 | #endif | |
1036 | ||
39601a7f VZ |
1037 | private: |
1038 | // Assignment functions | |
45de347c VZ |
1039 | void AssignAny(const wxAny& any) |
1040 | { | |
986a5956 SC |
1041 | // Must delete value - CopyBuffer() never does that |
1042 | m_type->DeleteValue(m_buffer); | |
24985a9b JS |
1043 | |
1044 | wxAnyValueType* newType = any.m_type; | |
1045 | ||
986a5956 | 1046 | if ( !newType->IsSameType(m_type) ) |
24985a9b JS |
1047 | m_type = newType; |
1048 | ||
1049 | newType->CopyBuffer(any.m_buffer, m_buffer); | |
45de347c | 1050 | } |
39601a7f | 1051 | |
0bf14ab8 JS |
1052 | #if wxUSE_VARIANT |
1053 | void AssignVariant(const wxVariant& variant) | |
1054 | { | |
1055 | wxVariantData* data = variant.GetData(); | |
1056 | ||
1057 | if ( data && data->GetAsAny(this) ) | |
1058 | return; | |
1059 | ||
1060 | m_type->DeleteValue(m_buffer); | |
1061 | ||
1062 | if ( variant.IsNull() ) | |
1063 | { | |
1064 | // Init as Null | |
1065 | m_type = wxAnyNullValueType; | |
1066 | } | |
1067 | else | |
1068 | { | |
1069 | // If everything else fails, wrap the whole wxVariantData | |
0cc226ad | 1070 | m_type = wxAnyValueTypeImpl<wxVariantData*>::sm_instance.get(); |
0bf14ab8 JS |
1071 | wxAnyValueTypeImpl<wxVariantData*>::SetValue(data, m_buffer); |
1072 | } | |
1073 | } | |
1074 | #endif | |
1075 | ||
39601a7f VZ |
1076 | template<typename T> |
1077 | void Assign(const T &value) | |
1078 | { | |
1079 | m_type->DeleteValue(m_buffer); | |
0cc226ad | 1080 | m_type = wxAnyValueTypeImpl<T>::sm_instance.get(); |
39601a7f VZ |
1081 | wxAnyValueTypeImpl<T>::SetValue(value, m_buffer); |
1082 | } | |
1083 | ||
1084 | // Data | |
39601a7f | 1085 | wxAnyValueBuffer m_buffer; |
04110679 | 1086 | wxAnyValueType* m_type; |
39601a7f VZ |
1087 | }; |
1088 | ||
1089 | ||
1090 | // | |
1091 | // This method of checking the type is compatible with VC6 | |
1092 | #define wxANY_CHECK_TYPE(any, T) \ | |
d1358fcb | 1093 | wxANY_VALUE_TYPE_CHECK_TYPE((any).GetType(), T) |
39601a7f VZ |
1094 | |
1095 | ||
1096 | // | |
1097 | // This method of getting the value is compatible with VC6 | |
1098 | #define wxANY_AS(any, T) \ | |
d1358fcb | 1099 | (any).As(static_cast<T*>(NULL)) |
39601a7f VZ |
1100 | |
1101 | ||
1102 | template<typename T> | |
49ddcdf9 | 1103 | inline bool wxAnyValueType::CheckType(T* reserved) const |
39601a7f VZ |
1104 | { |
1105 | wxUnusedVar(reserved); | |
1106 | return wxAnyValueTypeImpl<T>::IsSameClass(this); | |
1107 | } | |
1108 | ||
f41d5991 | 1109 | WX_DECLARE_LIST_WITH_DECL(wxAny, wxAnyList, class WXDLLIMPEXP_BASE); |
39601a7f VZ |
1110 | |
1111 | #endif // wxUSE_ANY | |
1112 | ||
1113 | #endif // _WX_ANY_H_ |