Add wxWeakRef::element_type, remove unnecessary assignment operator.
[wxWidgets.git] / include / wx / weakref.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/weakref.h
3 // Purpose: wxWeakRef - Generic weak references for wxWidgets
4 // Author: Arne Steinarson
5 // Created: 27 Dec 07
6 // RCS-ID: $Id$
7 // Copyright: (c) 2007 Arne Steinarson
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifndef _WX_WEAKREF_H_
12 #define _WX_WEAKREF_H_
13
14 #include "wx/tracker.h"
15
16
17 // Some compilers (VC6, Borland, g++ < 3.3) have problem with template specialization.
18 // However, this is only used for optimization purposes (a smaller wxWeakRef pointer)
19 // (and the corner case of wxWeakRef<wxObject>). So for those compilers, we can fall
20 // back to the non-optimal case, where we use a the same type of weak ref (static one)
21 // in all cases. See defs.h for various setting these defines depending on compiler.
22
23 #if !defined(HAVE_PARTIAL_SPECIALIZATION) || \
24 !defined(HAVE_TEMPLATE_OVERLOAD_RESOLUTION) || \
25 (defined(__GNUC__) && !wxCHECK_GCC_VERSION(3, 3))
26 #define USE_ONLY_STATIC_WEAKREF
27 #endif
28
29
30 #ifndef USE_ONLY_STATIC_WEAKREF
31
32 // Avoid including this for simpler compilers
33 #include "wx/meta/convertible.h"
34 #include "wx/meta/int2type.h"
35
36 template <class T>
37 struct wxIsStaticTrackable
38 {
39 enum { value = wxConvertibleTo<T, wxTrackable>::value };
40 };
41
42 #endif // !USE_ONLY_STATIC_WEAKREF
43
44
45 // Weak ref implementation when T has wxTrackable as a known base class
46 template <class T>
47 class wxWeakRefStatic : public wxTrackerNode
48 {
49 public:
50 wxWeakRefStatic() : m_pobj(NULL) { }
51
52 void Release()
53 {
54 // Release old object if any
55 if ( m_pobj )
56 {
57 // Remove ourselves from object tracker list
58 wxTrackable *pt = static_cast<wxTrackable*>(m_pobj);
59 pt->RemoveNode(this);
60 m_pobj = NULL;
61 }
62 }
63
64 virtual void OnObjectDestroy()
65 {
66 // Tracked object itself removes us from list of trackers
67 wxASSERT(m_pobj != NULL);
68 m_pobj = NULL;
69 }
70
71 protected:
72 void Assign(T* pobj)
73 {
74 if ( m_pobj == pobj )
75 return;
76
77 Release();
78
79 // Now set new trackable object
80 if ( pobj )
81 {
82 // Add ourselves to object tracker list
83 wxTrackable *pt = static_cast<wxTrackable*>(pobj);
84 pt->AddNode(this);
85 m_pobj = pobj;
86 }
87 }
88
89 void AssignCopy(const wxWeakRefStatic& wr)
90 {
91 Assign( wr.m_pobj );
92 }
93
94 T *m_pobj;
95 };
96
97
98
99 #ifndef USE_ONLY_STATIC_WEAKREF
100
101 template<class T,bool use_static>
102 struct wxWeakRefImpl;
103
104 // Intermediate class, to select the static case above.
105 template <class T>
106 struct wxWeakRefImpl<T, true> : public wxWeakRefStatic<T>
107 {
108 enum { value = 1 };
109 };
110
111 // Weak ref implementation when T does not have wxTrackable as known base class
112 template<class T>
113 struct wxWeakRefImpl<T, false> : public wxTrackerNode
114 {
115 void Release()
116 {
117 // Release old object if any
118 if ( m_pobj )
119 {
120 // Remove ourselves from object tracker list
121 m_ptbase->RemoveNode(this);
122 m_pobj = NULL;
123 m_ptbase = NULL;
124 }
125 }
126
127 virtual void OnObjectDestroy()
128 {
129 // Tracked object itself removes us from list of trackers
130 wxASSERT(m_pobj != NULL);
131 m_pobj = NULL;
132 m_ptbase = NULL;
133 }
134
135 protected:
136 wxWeakRefImpl() : m_pobj(NULL), m_ptbase(NULL) { }
137
138 // Assign receives most derived class here and can use that
139 template <class TDerived>
140 void Assign( TDerived* pobj )
141 {
142 AssignHelper( pobj, wxInt2Type<wxIsStaticTrackable<TDerived>::value>() );
143 }
144
145 template <class TDerived>
146 void AssignHelper(TDerived* pobj, wxInt2Type<true>)
147 {
148 wxTrackable *ptbase = static_cast<wxTrackable*>(pobj);
149 DoAssign( pobj, ptbase );
150 }
151
152 #ifdef HAVE_DYNAMIC_CAST
153 void AssignHelper(T* pobj, wxInt2Type<false>)
154 {
155 // A last way to get a trackable pointer
156 wxTrackable *ptbase = dynamic_cast<wxTrackable*>(pobj);
157 if ( ptbase )
158 {
159 DoAssign( pobj, ptbase );
160 }
161 else
162 {
163 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
164
165 Release();
166 }
167 }
168 #endif // HAVE_DYNAMIC_CAST
169
170 void AssignCopy(const wxWeakRefImpl& wr)
171 {
172 DoAssign(wr.m_pobj, wr.m_ptbase);
173 }
174
175 void DoAssign( T* pobj, wxTrackable *ptbase ) {
176 if( m_pobj==pobj ) return;
177 Release();
178
179 // Now set new trackable object
180 if( pobj )
181 {
182 // Add ourselves to object tracker list
183 wxASSERT( ptbase );
184 ptbase->AddNode( this );
185 m_pobj = pobj;
186 m_ptbase = ptbase;
187 }
188 }
189
190 T *m_pobj;
191 wxTrackable *m_ptbase;
192 };
193
194 #endif // #ifndef USE_ONLY_STATIC_WEAKREF
195
196
197
198 // A weak reference to an object of type T, where T has base wxTrackable
199 // (usually statically but if not dynamic_cast<> is tried).
200 template <class T>
201 class wxWeakRef : public
202 #ifdef USE_ONLY_STATIC_WEAKREF
203 wxWeakRefStatic<T>
204 #else
205 wxWeakRefImpl<T, wxIsStaticTrackable<T>::value != 0>
206 #endif
207 {
208 public:
209 typedef T element_type;
210
211 // Default ctor
212 wxWeakRef() { }
213
214 // When we have the full type here, static_cast<> will always work
215 // (or give a straight compiler error).
216 template <class TDerived>
217 wxWeakRef(TDerived* pobj)
218 {
219 Assign(pobj);
220 }
221
222 // We need this copy ctor, since otherwise a default compiler (binary) copy
223 // happens (if embedded as an object member).
224 wxWeakRef(const wxWeakRef<T>& wr)
225 {
226 Assign(wr.get());
227 }
228
229 wxWeakRef<T>& operator=(const wxWeakRef<T>& wr)
230 {
231 AssignCopy(wr);
232 return *this;
233 }
234
235 virtual ~wxWeakRef() { this->Release(); }
236
237 // Smart pointer functions
238 T& operator*() const { return *this->m_pobj; }
239 T* operator->() const { return this->m_pobj; }
240
241 T* get() const { return this->m_pobj; }
242 operator T*() const { return this->m_pobj; }
243 };
244
245
246 #ifdef HAVE_DYNAMIC_CAST
247
248 // Weak ref implementation assign objects are queried for wxTrackable
249 // using dynamic_cast<>
250 template <class T>
251 class wxWeakRefDynamic : public wxTrackerNode
252 {
253 public:
254 wxWeakRefDynamic() : m_pobj(NULL) { }
255
256 wxWeakRefDynamic(T* pobj) : m_pobj(pobj)
257 {
258 Assign(pobj);
259 }
260
261 wxWeakRefDynamic(const wxWeakRef<T>& wr)
262 {
263 Assign(wr.get());
264 }
265
266 virtual ~wxWeakRefDynamic() { Release(); }
267
268 // Smart pointer functions
269 T& operator*() const { wxASSERT(m_pobj); return *m_pobj; }
270 T* operator->() const { wxASSERT(m_pobj); return m_pobj; }
271
272 T* get() const { return m_pobj; }
273 operator T* () const { return m_pobj; }
274
275 T* operator = (T* pobj) { Assign(pobj); return m_pobj; }
276
277 // Assign from another weak ref, point to same object
278 T* operator = (const wxWeakRef<T> &wr) { Assign( wr.get() ); return m_pobj; }
279
280 void Release()
281 {
282 // Release old object if any
283 if( m_pobj )
284 {
285 // Remove ourselves from object tracker list
286 wxTrackable *pt = dynamic_cast<wxTrackable*>(m_pobj);
287 wxASSERT(pt);
288 pt->RemoveNode(this);
289 m_pobj = NULL;
290 }
291 }
292
293 virtual void OnObjectDestroy()
294 {
295 wxASSERT_MSG(m_pobj, "tracked object should have removed us itself");
296
297 m_pobj = NULL;
298 }
299
300 protected:
301 void Assign(T *pobj)
302 {
303 if ( m_pobj == pobj )
304 return;
305
306 Release();
307
308 // Now set new trackable object
309 if ( pobj )
310 {
311 // Add ourselves to object tracker list
312 wxTrackable *pt = dynamic_cast<wxTrackable*>(pobj);
313 if ( pt )
314 {
315 pt->AddNode(this);
316 m_pobj = pobj;
317 }
318 else
319 {
320 // If the object we want to track does not support wxTackable, then
321 // log a message and keep the NULL object pointer.
322 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
323 }
324 }
325 }
326
327 T *m_pobj;
328 };
329
330 #endif // #ifdef HAVE_DYNAMIC_CAST
331
332
333 // Provide some basic types of weak references
334 class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
335 class WXDLLIMPEXP_FWD_CORE wxWindow;
336
337
338 typedef wxWeakRef<wxEvtHandler> wxEvtHandlerRef;
339 typedef wxWeakRef<wxWindow> wxWindowRef;
340
341 #endif // _WX_WEAKREF_H_
342