1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxWeakRef - Generic weak references for wxWidgets
4 // Author: Arne Steinarson
7 // Copyright: (c) 2007 Arne Steinarson
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 #ifndef _WX_WEAKREF_H_
12 #define _WX_WEAKREF_H_
14 #include "wx/tracker.h"
17 // Some compilers (VC6, Borland, otehrs?) 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.
23 #if !defined(HAVE_PARTIAL_SPECIALIZATION) || !defined(HAVE_TEMPLATE_OVERLOAD_RESOLUTION)
24 #define USE_ONLY_STATIC_WEAKREF
28 #ifndef USE_ONLY_STATIC_WEAKREF
30 // Avoid including this for simpler compilers
31 #include "wx/meta/convertible.h"
32 #include "wx/meta/int2type.h"
35 struct wxIsStaticTrackable
37 enum { value
= wxConvertibleTo
<T
, wxTrackable
>::value
};
40 #endif // !USE_ONLY_STATIC_WEAKREF
43 // Weak ref implementation when T has wxTrackable as a known base class
45 class wxWeakRefStatic
: public wxTrackerNode
48 wxWeakRefStatic() : m_pobj(NULL
) { }
52 // Release old object if any
55 // Remove ourselves from object tracker list
56 wxTrackable
*pt
= static_cast<wxTrackable
*>(m_pobj
);
70 // Now set new trackable object
73 // Add ourselves to object tracker list
74 wxTrackable
*pt
= static_cast<wxTrackable
*>(pobj
);
80 void AssignCopy(const wxWeakRefStatic
& wr
)
85 virtual void OnObjectDestroy()
87 // Tracked object itself removes us from list of trackers
88 wxASSERT( m_pobj
!=NULL
);
97 #ifndef USE_ONLY_STATIC_WEAKREF
99 template<class T
,bool use_static
>
100 struct wxWeakRefImpl
;
102 // Intermediate class, to select the static case above.
104 struct wxWeakRefImpl
<T
, true> : public wxWeakRefStatic
<T
>
109 // Weak ref implementation when T does not have wxTrackable as known base class
111 struct wxWeakRefImpl
<T
, false> : public wxTrackerNode
115 // Release old object if any
118 // Remove ourselves from object tracker list
119 m_ptbase
->RemoveNode(this);
126 wxWeakRefImpl() : m_pobj(NULL
), m_ptbase(NULL
) { }
128 // Assign receives most derived class here and can use that
129 template <class TDerived
>
130 void Assign( TDerived
* pobj
)
132 AssignHelper( pobj
, wxInt2Type
<wxIsStaticTrackable
<TDerived
>::value
>() );
135 template <class TDerived
>
136 void AssignHelper(TDerived
* pobj
, wxInt2Type
<true>)
138 wxTrackable
*ptbase
= static_cast<wxTrackable
*>(pobj
);
139 DoAssign( pobj
, ptbase
);
142 #ifdef HAVE_DYNAMIC_CAST
143 void AssignHelper(T
* pobj
, wxInt2Type
<false>)
145 // A last way to get a trackable pointer
146 wxTrackable
*ptbase
= dynamic_cast<wxTrackable
*>(pobj
);
149 DoAssign( pobj
, ptbase
);
153 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
158 #endif // HAVE_DYNAMIC_CAST
160 void AssignCopy(const wxWeakRefImpl
& wr
)
162 DoAssign(wr
.m_pobj
, wr
.m_ptbase
);
165 void DoAssign( T
* pobj
, wxTrackable
*ptbase
) {
166 if( m_pobj
==pobj
) return;
169 // Now set new trackable object
172 // Add ourselves to object tracker list
174 ptbase
->AddNode( this );
180 virtual void OnObjectDestroy()
182 // Tracked object itself removes us from list of trackers
183 wxASSERT( m_pobj
!=NULL
);
189 wxTrackable
*m_ptbase
;
192 #endif // #ifndef USE_ONLY_STATIC_WEAKREF
196 // A weak reference to an object of type T, where T has base wxTrackable
197 // (usually statically but if not dynamic_cast<> is tried).
199 class wxWeakRef
: public
200 #ifdef USE_ONLY_STATIC_WEAKREF
203 wxWeakRefImpl
<T
, wxIsStaticTrackable
<T
>::value
>
210 // When we have the full type here, static_cast<> will always work
211 // (or give a straight compiler error).
212 template <class TDerived
>
213 wxWeakRef(TDerived
* pobj
)
218 // We need this copy ctor, since otherwise a default compiler (binary) copy
219 // happens (if embedded as an object member).
220 wxWeakRef(const wxWeakRef
<T
>& wr
)
225 template <class TDerived
>
226 wxWeakRef
<T
>& operator=(TDerived
* pobj
)
232 wxWeakRef
<T
>& operator=(const wxWeakRef
<T
>& wr
)
238 virtual ~wxWeakRef() { this->Release(); }
240 // Smart pointer functions
241 T
& operator*() const { return *this->m_pobj
; }
242 T
* operator->() const { return this->m_pobj
; }
244 T
* get() const { return this->m_pobj
; }
245 operator T
*() const { return this->m_pobj
; }
249 #ifdef HAVE_DYNAMIC_CAST
251 // Weak ref implementation assign objects are queried for wxTrackable
252 // using dynamic_cast<>
254 class wxWeakRefDynamic
: public wxTrackerNode
257 wxWeakRefDynamic() : m_pobj(NULL
) { }
259 wxWeakRefDynamic(T
* pobj
) : m_pobj(pobj
)
264 wxWeakRefDynamic(const wxWeakRef
<T
>& wr
)
269 virtual ~wxWeakRefDynamic() { Release(); }
271 // Smart pointer functions
272 T
& operator*() const { wxASSERT(m_pobj
); return *m_pobj
; }
273 T
* operator->() const { wxASSERT(m_pobj
); return m_pobj
; }
275 T
* get() const { return m_pobj
; }
276 operator T
* () const { return m_pobj
; }
278 T
* operator = (T
* pobj
) { Assign(pobj
); return m_pobj
; }
280 // Assign from another weak ref, point to same object
281 T
* operator = (const wxWeakRef
<T
> &wr
) { Assign( wr
.get() ); return m_pobj
; }
285 // Release old object if any
288 // Remove ourselves from object tracker list
289 wxTrackable
*pt
= dynamic_cast<wxTrackable
*>(m_pobj
);
291 pt
->RemoveNode(this);
299 if ( m_pobj
== pobj
)
304 // Now set new trackable object
307 // Add ourselves to object tracker list
308 wxTrackable
*pt
= dynamic_cast<wxTrackable
*>(pobj
);
316 // If the object we want to track does not support wxTackable, then
317 // log a message and keep the NULL object pointer.
318 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
323 virtual void OnObjectDestroy()
325 wxASSERT_MSG( m_pobj
, "tracked object should have removed us itself" );
333 #endif // #ifdef HAVE_DYNAMIC_CAST
336 // Provide some basic types of weak references
337 class WXDLLIMPEXP_FWD_BASE wxEvtHandler
;
338 class WXDLLIMPEXP_FWD_CORE wxWindow
;
341 typedef wxWeakRef
<wxEvtHandler
> wxEvtHandlerRef
;
342 typedef wxWeakRef
<wxWindow
> wxWindowRef
;
344 #endif // _WX_WEAKREF_H_