]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: any.h | |
3 | // Purpose: interface of wxAny | |
4 | // Author: wxWidgets team | |
5 | // Licence: wxWindows licence | |
6 | ///////////////////////////////////////////////////////////////////////////// | |
7 | ||
8 | ||
9 | /** | |
10 | @class wxAny | |
11 | ||
12 | The wxAny class represents a container for any type. Its value | |
13 | can be changed at run time, possibly to a different type of value. | |
14 | ||
15 | wxAny is a backwards-incompatible (but convertible) successor class for | |
16 | wxVariant, essentially doing the same thing in a more modern, template- | |
17 | based manner and with transparent support for any user data type. | |
18 | ||
19 | Some pseudo-code'ish example of use with arbitrary user data: | |
20 | ||
21 | @code | |
22 | void SomeFunction() | |
23 | { | |
24 | MyClass myObject; | |
25 | wxAny any = myObject; | |
26 | ||
27 | // Do something | |
28 | // ... | |
29 | ||
30 | // Let's do a sanity check to make sure that any still holds | |
31 | // data of correct type. | |
32 | if ( any.CheckType<MyClass>() ) | |
33 | { | |
34 | // Thank goodness, still a correct type. | |
35 | MyClass myObject2 = any.As<MyClass>(); | |
36 | } | |
37 | else | |
38 | { | |
39 | // Something has gone horribly wrong! | |
40 | wxFAIL(); | |
41 | } | |
42 | } | |
43 | @endcode | |
44 | ||
45 | When compared to wxVariant, there are various internal implementation | |
46 | differences as well. For instance, wxAny only allocates separate data | |
47 | object in heap for large objects (i.e. ones with size more than | |
48 | WX_ANY_VALUE_BUFFER_SIZE, which at the time of writing is 16 bytes). | |
49 | ||
50 | @note When performing conversions between strings and floating point | |
51 | numbers, the representation of numbers in C locale is always used. | |
52 | I.e. @code wxAny("1.23").GetAs<double>() @endcode will always work, | |
53 | even if the current locale uses comma as decimal separator. | |
54 | ||
55 | @library{wxbase} | |
56 | @category{data} | |
57 | ||
58 | @see wxAnyValueType, wxVariant, @ref overview_cpp_rtti_disabled | |
59 | */ | |
60 | class wxAny | |
61 | { | |
62 | public: | |
63 | /** | |
64 | Default constructor. It seeds the object with a null value. | |
65 | */ | |
66 | wxAny(); | |
67 | ||
68 | /** | |
69 | Constructs wxAny from data. | |
70 | */ | |
71 | template<typename T> | |
72 | wxAny(const T& value); | |
73 | ||
74 | /** | |
75 | Constructs wxAny from another wxAny. | |
76 | */ | |
77 | wxAny(const wxAny& any); | |
78 | ||
79 | /** | |
80 | Constructs wxAny, converting value from wxVariant. | |
81 | ||
82 | @remarks Because of this conversion, it is not usually possible to | |
83 | have wxAny that actually holds a wxVariant. If wxVariant | |
84 | cannot be converted to a specific data type, wxAny will then | |
85 | hold and manage reference to wxVariantData* similar to how | |
86 | wxVariant does. | |
87 | */ | |
88 | wxAny(const wxVariant& variant); | |
89 | ||
90 | /** | |
91 | Destructor. | |
92 | */ | |
93 | ~wxAny(); | |
94 | ||
95 | /** | |
96 | This template function converts wxAny into given type. In most cases | |
97 | no type conversion is performed, so if the type is incorrect an | |
98 | assertion failure will occur. | |
99 | ||
100 | @remarks For conveniency, conversion is done when T is wxString. This | |
101 | is useful when a string literal (which are treated as | |
102 | const char* and const wchar_t*) has been assigned to wxAny. | |
103 | ||
104 | This template function may not work properly with Visual C++ | |
105 | 6. For full compiler compatibility, please use | |
106 | wxANY_AS(any, T) macro instead. | |
107 | */ | |
108 | template<typename T> | |
109 | T As() const; | |
110 | ||
111 | /** | |
112 | Use this template function for checking if this wxAny holds | |
113 | a specific C++ data type. | |
114 | ||
115 | @remarks This template function may not work properly with Visual C++ | |
116 | 6. For full compiler compatibility, please use | |
117 | wxANY_CHECK_TYPE(any, T) macro instead. | |
118 | ||
119 | @see wxAnyValueType::CheckType() | |
120 | */ | |
121 | template<typename T> | |
122 | bool CheckType() const; | |
123 | ||
124 | /** | |
125 | Template function that retrieves and converts the value of this | |
126 | wxAny to the type that T* value is. | |
127 | ||
128 | @return Returns @true if conversion was successful. | |
129 | */ | |
130 | template<typename T> | |
131 | bool GetAs(T* value) const; | |
132 | ||
133 | /** | |
134 | Specialization of GetAs() that allows conversion of wxAny into | |
135 | wxVariant. | |
136 | ||
137 | @return Returns @true if conversion was successful. Conversion usually | |
138 | only fails if variant used custom wxVariantData that did not | |
139 | implement the wxAny to wxVariant conversion functions. | |
140 | */ | |
141 | bool GetAs(wxVariant* value) const; | |
142 | ||
143 | /** | |
144 | Returns the value type as wxAnyValueType instance. | |
145 | ||
146 | @remarks You cannot reliably test whether two wxAnys are of | |
147 | same value type by simply comparing return values | |
148 | of wxAny::GetType(). Instead, use wxAny::HasSameType(). | |
149 | ||
150 | @see HasSameType() | |
151 | */ | |
152 | const wxAnyValueType* GetType() const; | |
153 | ||
154 | /** | |
155 | Returns @true if this and another wxAny have the same | |
156 | value type. | |
157 | */ | |
158 | bool HasSameType(const wxAny& other) const; | |
159 | ||
160 | /** | |
161 | Tests if wxAny is null (that is, whether there is no data). | |
162 | */ | |
163 | bool IsNull() const; | |
164 | ||
165 | /** | |
166 | Makes wxAny null (that is, clears it). | |
167 | */ | |
168 | void MakeNull(); | |
169 | ||
170 | //@{ | |
171 | /** | |
172 | @name Assignment operators | |
173 | */ | |
174 | template<typename T> | |
175 | wxAny& operator=(const T &value); | |
176 | wxAny& operator=(const wxAny &any); | |
177 | wxAny& operator=(const wxVariant &variant); | |
178 | //@} | |
179 | ||
180 | //@{ | |
181 | /** | |
182 | @name Equality operators | |
183 | ||
184 | @remarks Generic template-based comparison operators have not been | |
185 | provided for various code consistency reasons, so for custom | |
186 | data types you have do something like this: | |
187 | ||
188 | @code | |
189 | if ( any.CheckType<MyClass*>() && | |
190 | any.As<MyClass*>() == myObjectPtr ) | |
191 | { | |
192 | // Do something if any stores myObjectPtr | |
193 | } | |
194 | @endcode | |
195 | */ | |
196 | bool operator==(signed char value) const; | |
197 | bool operator==(signed short value) const; | |
198 | bool operator==(signed int value) const; | |
199 | bool operator==(signed long value) const; | |
200 | bool operator==(wxLongLong_t value) const; | |
201 | bool operator==(unsigned char value) const; | |
202 | bool operator==(unsigned short value) const; | |
203 | bool operator==(unsigned int value) const; | |
204 | bool operator==(unsigned long value) const; | |
205 | bool operator==(wxULongLong_t value) const; | |
206 | bool operator==(float value) const; | |
207 | bool operator==(double value) const; | |
208 | bool operator==(bool value) const; | |
209 | bool operator==(const char* value) const; | |
210 | bool operator==(const wchar_t* value) const; | |
211 | bool operator==(const wxString& value) const; | |
212 | //@} | |
213 | ||
214 | //@{ | |
215 | /** | |
216 | @name Inequality operators | |
217 | */ | |
218 | bool operator!=(signed char value) const; | |
219 | bool operator!=(signed short value) const; | |
220 | bool operator!=(signed int value) const; | |
221 | bool operator!=(signed long value) const; | |
222 | bool operator!=(wxLongLong_t value) const; | |
223 | bool operator!=(unsigned char value) const; | |
224 | bool operator!=(unsigned short value) const; | |
225 | bool operator!=(unsigned int value) const; | |
226 | bool operator!=(unsigned long value) const; | |
227 | bool operator!=(wxULongLong_t value) const; | |
228 | bool operator!=(float value) const; | |
229 | bool operator!=(double value) const; | |
230 | bool operator!=(bool value) const; | |
231 | bool operator!=(const char* value) const; | |
232 | bool operator!=(const wchar_t* value) const; | |
233 | bool operator!=(const wxString& value) const; | |
234 | //@} | |
235 | }; | |
236 | ||
237 | /** | |
238 | This is value getter macro that is more compatible with older | |
239 | compilers, such as Visual C++ 6.0. | |
240 | */ | |
241 | #define wxANY_AS(any, T) | |
242 | ||
243 | ||
244 | /** | |
245 | This is type checking macro that is more compatible with older | |
246 | compilers, such as Visual C++ 6.0. | |
247 | */ | |
248 | #define wxANY_CHECK_TYPE(any, T) | |
249 | ||
250 | ||
251 | /** | |
252 | Size of the wxAny value buffer. | |
253 | */ | |
254 | enum | |
255 | { | |
256 | WX_ANY_VALUE_BUFFER_SIZE = 16 | |
257 | }; | |
258 | ||
259 | /** | |
260 | Type for buffer within wxAny for holding data. | |
261 | */ | |
262 | union wxAnyValueBuffer | |
263 | { | |
264 | void* m_ptr; | |
265 | wxByte m_buffer[WX_ANY_VALUE_BUFFER_SIZE]; | |
266 | }; | |
267 | ||
268 | ||
269 | /** | |
270 | @class wxAnyValueType | |
271 | ||
272 | wxAnyValueType is base class for value type functionality for C++ data | |
273 | types used with wxAny. Usually the default template will create a | |
274 | satisfactory wxAnyValueType implementation for a data type, but | |
275 | sometimes you may need to add some customization. To do this you will need | |
276 | to add specialized template of wxAnyValueTypeImpl<>. Often your only | |
277 | need may be to add dynamic type conversion which would be done like | |
278 | this: | |
279 | ||
280 | @code | |
281 | template<> | |
282 | class wxAnyValueTypeImpl<MyClass> : | |
283 | public wxAnyValueTypeImplBase<MyClass> | |
284 | { | |
285 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>) | |
286 | public: | |
287 | wxAnyValueTypeImpl() : | |
288 | wxAnyValueTypeImplBase<MyClass>() { } | |
289 | virtual ~wxAnyValueTypeImpl() { } | |
290 | ||
291 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
292 | wxAnyValueType* dstType, | |
293 | wxAnyValueBuffer& dst) const | |
294 | { | |
295 | // GetValue() is a static member function implemented | |
296 | // in wxAnyValueTypeImplBase<>. | |
297 | MyClass value = GetValue(src); | |
298 | ||
299 | // TODO: Convert value from src buffer to destination | |
300 | // type and buffer. If cannot be done, return | |
301 | // false. This is a simple sample. | |
302 | if ( dstType->CheckType<wxString>() ) | |
303 | { | |
304 | wxString s = value.ToString(); | |
305 | wxAnyValueTypeImpl<wxString>::SetValue(s, dst); | |
306 | } | |
307 | else | |
308 | { | |
309 | return false; | |
310 | } | |
311 | } | |
312 | }; | |
313 | ||
314 | // | |
315 | // Following must be placed somewhere in your source code | |
316 | WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>) | |
317 | @endcode | |
318 | ||
319 | wxAnyValueTypeImplBase<> template, from which we inherit in the above | |
320 | example, contains the bulk of the default wxAnyValueTypeImpl<> template | |
321 | implementation, and as such allows you to easily add some minor | |
322 | customization. | |
323 | ||
324 | If you need a have complete control over the type interpretation, you | |
325 | will need to derive a class directly from wxAnyValueType, like this: | |
326 | ||
327 | @code | |
328 | template <> | |
329 | class wxAnyValueTypeImpl<MyClass> : public wxAnyValueType | |
330 | { | |
331 | WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>) | |
332 | public: | |
333 | virtual void DeleteValue(wxAnyValueBuffer& buf) const | |
334 | { | |
335 | // TODO: Free the data in buffer | |
336 | // It is important to clear the buffer like this | |
337 | // at the end of DeleteValue(). | |
338 | buf.m_ptr = NULL; | |
339 | } | |
340 | ||
341 | virtual void CopyBuffer(const wxAnyValueBuffer& src, | |
342 | wxAnyValueBuffer& dst) const | |
343 | { | |
344 | // TODO: Copy value from one buffer to another. | |
345 | // dst is already uninitialized and does not | |
346 | // need to be freed. | |
347 | } | |
348 | ||
349 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
350 | wxAnyValueType* dstType, | |
351 | wxAnyValueBuffer& dst) const | |
352 | { | |
353 | // TODO: Convert value from src buffer to destination | |
354 | // type and buffer. | |
355 | } | |
356 | ||
357 | // | |
358 | // Following static functions must be implemented | |
359 | // | |
360 | ||
361 | static void SetValue(const T& value, | |
362 | wxAnyValueBuffer& buf) | |
363 | { | |
364 | // TODO: Store value into buf. | |
365 | } | |
366 | ||
367 | static const T& GetValue(const wxAnyValueBuffer& buf) | |
368 | { | |
369 | // TODO: Return reference to value stored in buffer. | |
370 | } | |
371 | }; | |
372 | ||
373 | // | |
374 | // Following must be placed somewhere in your source code | |
375 | WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<MyClass>) | |
376 | ||
377 | @endcode | |
378 | ||
379 | @library{wxbase} | |
380 | @category{data} | |
381 | ||
382 | @see wxAny | |
383 | */ | |
384 | class wxAnyValueType | |
385 | { | |
386 | public: | |
387 | /** | |
388 | Default constructor. | |
389 | */ | |
390 | wxAnyValueType(); | |
391 | ||
392 | /** | |
393 | Destructor. | |
394 | */ | |
395 | virtual ~wxAnyValueType(); | |
396 | ||
397 | /** | |
398 | Use this template function for checking if wxAnyValueType represents | |
399 | a specific C++ data type. | |
400 | ||
401 | @remarks This template function does not work on some older compilers | |
402 | (such as Visual C++ 6.0). For full compiler compatibility | |
403 | please use wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) macro | |
404 | instead. | |
405 | ||
406 | @see wxAny::CheckType() | |
407 | */ | |
408 | template <typename T> | |
409 | bool CheckType() const; | |
410 | ||
411 | /** | |
412 | Convert value into buffer of different type. Return false if | |
413 | not possible. | |
414 | */ | |
415 | virtual bool ConvertValue(const wxAnyValueBuffer& src, | |
416 | wxAnyValueType* dstType, | |
417 | wxAnyValueBuffer& dst) const = 0; | |
418 | ||
419 | /** | |
420 | Implement this for buffer-to-buffer copy. | |
421 | ||
422 | @param src | |
423 | This is the source data buffer. | |
424 | ||
425 | @param dst | |
426 | This is the destination data buffer that is in either | |
427 | uninitialized or freed state. | |
428 | */ | |
429 | virtual void CopyBuffer(const wxAnyValueBuffer& src, | |
430 | wxAnyValueBuffer& dst) const = 0; | |
431 | ||
432 | /** | |
433 | This function is called every time the data in wxAny | |
434 | buffer needs to be freed. | |
435 | */ | |
436 | virtual void DeleteValue(wxAnyValueBuffer& buf) const = 0; | |
437 | ||
438 | /** | |
439 | This function is used for internal type matching. | |
440 | */ | |
441 | virtual bool IsSameType(const wxAnyValueType* otherType) const = 0; | |
442 | }; | |
443 | ||
444 | /** | |
445 | This is type checking macro that is more compatible with older | |
446 | compilers, such as Visual C++ 6.0. | |
447 | */ | |
448 | #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) |