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, 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.
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
30 #ifndef USE_ONLY_STATIC_WEAKREF
32 // Avoid including this for simpler compilers
33 #include "wx/meta/convertible.h"
34 #include "wx/meta/int2type.h"
37 struct wxIsStaticTrackable
39 enum { value
= wxConvertibleTo
<T
, wxTrackable
>::value
};
42 #endif // !USE_ONLY_STATIC_WEAKREF
45 // Weak ref implementation when T has wxTrackable as a known base class
47 class wxWeakRefStatic
: public wxTrackerNode
50 wxWeakRefStatic() : m_pobj(NULL
) { }
54 // Release old object if any
57 // Remove ourselves from object tracker list
58 wxTrackable
*pt
= static_cast<wxTrackable
*>(m_pobj
);
64 virtual void OnObjectDestroy()
66 // Tracked object itself removes us from list of trackers
67 wxASSERT(m_pobj
!= NULL
);
79 // Now set new trackable object
82 // Add ourselves to object tracker list
83 wxTrackable
*pt
= static_cast<wxTrackable
*>(pobj
);
89 void AssignCopy(const wxWeakRefStatic
& wr
)
99 #ifndef USE_ONLY_STATIC_WEAKREF
101 template<class T
,bool use_static
>
102 struct wxWeakRefImpl
;
104 // Intermediate class, to select the static case above.
106 struct wxWeakRefImpl
<T
, true> : public wxWeakRefStatic
<T
>
111 // Weak ref implementation when T does not have wxTrackable as known base class
113 struct wxWeakRefImpl
<T
, false> : public wxTrackerNode
117 // Release old object if any
120 // Remove ourselves from object tracker list
121 m_ptbase
->RemoveNode(this);
127 virtual void OnObjectDestroy()
129 // Tracked object itself removes us from list of trackers
130 wxASSERT(m_pobj
!= NULL
);
136 wxWeakRefImpl() : m_pobj(NULL
), m_ptbase(NULL
) { }
138 // Assign receives most derived class here and can use that
139 template <class TDerived
>
140 void Assign( TDerived
* pobj
)
142 AssignHelper( pobj
, wxInt2Type
<wxIsStaticTrackable
<TDerived
>::value
>() );
145 template <class TDerived
>
146 void AssignHelper(TDerived
* pobj
, wxInt2Type
<true>)
148 wxTrackable
*ptbase
= static_cast<wxTrackable
*>(pobj
);
149 DoAssign( pobj
, ptbase
);
152 #ifdef HAVE_DYNAMIC_CAST
153 void AssignHelper(T
* pobj
, wxInt2Type
<false>)
155 // A last way to get a trackable pointer
156 wxTrackable
*ptbase
= dynamic_cast<wxTrackable
*>(pobj
);
159 DoAssign( pobj
, ptbase
);
163 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
168 #endif // HAVE_DYNAMIC_CAST
170 void AssignCopy(const wxWeakRefImpl
& wr
)
172 DoAssign(wr
.m_pobj
, wr
.m_ptbase
);
175 void DoAssign( T
* pobj
, wxTrackable
*ptbase
) {
176 if( m_pobj
==pobj
) return;
179 // Now set new trackable object
182 // Add ourselves to object tracker list
184 ptbase
->AddNode( this );
191 wxTrackable
*m_ptbase
;
194 #endif // #ifndef USE_ONLY_STATIC_WEAKREF
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).
201 class wxWeakRef
: public
202 #ifdef USE_ONLY_STATIC_WEAKREF
205 wxWeakRefImpl
<T
, wxIsStaticTrackable
<T
>::value
!= 0>
212 // When we have the full type here, static_cast<> will always work
213 // (or give a straight compiler error).
214 template <class TDerived
>
215 wxWeakRef(TDerived
* pobj
)
220 // We need this copy ctor, since otherwise a default compiler (binary) copy
221 // happens (if embedded as an object member).
222 wxWeakRef(const wxWeakRef
<T
>& wr
)
227 template <class TDerived
>
228 wxWeakRef
<T
>& operator=(TDerived
* pobj
)
234 wxWeakRef
<T
>& operator=(const wxWeakRef
<T
>& wr
)
240 virtual ~wxWeakRef() { this->Release(); }
242 // Smart pointer functions
243 T
& operator*() const { return *this->m_pobj
; }
244 T
* operator->() const { return this->m_pobj
; }
246 T
* get() const { return this->m_pobj
; }
247 operator T
*() const { return this->m_pobj
; }
251 #ifdef HAVE_DYNAMIC_CAST
253 // Weak ref implementation assign objects are queried for wxTrackable
254 // using dynamic_cast<>
256 class wxWeakRefDynamic
: public wxTrackerNode
259 wxWeakRefDynamic() : m_pobj(NULL
) { }
261 wxWeakRefDynamic(T
* pobj
) : m_pobj(pobj
)
266 wxWeakRefDynamic(const wxWeakRef
<T
>& wr
)
271 virtual ~wxWeakRefDynamic() { Release(); }
273 // Smart pointer functions
274 T
& operator*() const { wxASSERT(m_pobj
); return *m_pobj
; }
275 T
* operator->() const { wxASSERT(m_pobj
); return m_pobj
; }
277 T
* get() const { return m_pobj
; }
278 operator T
* () const { return m_pobj
; }
280 T
* operator = (T
* pobj
) { Assign(pobj
); return m_pobj
; }
282 // Assign from another weak ref, point to same object
283 T
* operator = (const wxWeakRef
<T
> &wr
) { Assign( wr
.get() ); return m_pobj
; }
287 // Release old object if any
290 // Remove ourselves from object tracker list
291 wxTrackable
*pt
= dynamic_cast<wxTrackable
*>(m_pobj
);
293 pt
->RemoveNode(this);
298 virtual void OnObjectDestroy()
300 wxASSERT_MSG(m_pobj
, "tracked object should have removed us itself");
308 if ( m_pobj
== pobj
)
313 // Now set new trackable object
316 // Add ourselves to object tracker list
317 wxTrackable
*pt
= dynamic_cast<wxTrackable
*>(pobj
);
325 // If the object we want to track does not support wxTackable, then
326 // log a message and keep the NULL object pointer.
327 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
335 #endif // #ifdef HAVE_DYNAMIC_CAST
338 // Provide some basic types of weak references
339 class WXDLLIMPEXP_FWD_BASE wxEvtHandler
;
340 class WXDLLIMPEXP_FWD_CORE wxWindow
;
343 typedef wxWeakRef
<wxEvtHandler
> wxEvtHandlerRef
;
344 typedef wxWeakRef
<wxWindow
> wxWindowRef
;
346 #endif // _WX_WEAKREF_H_