1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxWeakRef - Generic weak references for wxWidgets
4 // Author: Arne Steinarson
6 // Copyright: (c) 2007 Arne Steinarson
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 #ifndef _WX_WEAKREF_H_
11 #define _WX_WEAKREF_H_
13 #include "wx/tracker.h"
16 // Some compilers (VC6, Borland, g++ < 3.3) have problem with template specialization.
17 // However, this is only used for optimization purposes (a smaller wxWeakRef pointer)
18 // (and the corner case of wxWeakRef<wxObject>). So for those compilers, we can fall
19 // back to the non-optimal case, where we use the same type of weak ref (static one)
20 // in all cases. See defs.h for various setting these defines depending on compiler.
22 #if !defined(HAVE_PARTIAL_SPECIALIZATION) || \
23 !defined(HAVE_TEMPLATE_OVERLOAD_RESOLUTION) || \
24 (defined(__GNUC__) && !wxCHECK_GCC_VERSION(3, 3))
25 #define USE_ONLY_STATIC_WEAKREF
29 #ifndef USE_ONLY_STATIC_WEAKREF
31 // Avoid including this for simpler compilers
32 #include "wx/meta/convertible.h"
33 #include "wx/meta/int2type.h"
36 struct wxIsStaticTrackable
38 enum { value
= wxConvertibleTo
<T
, wxTrackable
>::value
};
41 #endif // !USE_ONLY_STATIC_WEAKREF
44 // Weak ref implementation when T has wxTrackable as a known base class
46 class wxWeakRefStatic
: public wxTrackerNode
49 wxWeakRefStatic() : m_pobj(NULL
) { }
53 // Release old object if any
56 // Remove ourselves from object tracker list
57 wxTrackable
*pt
= static_cast<wxTrackable
*>(m_pobj
);
63 virtual void OnObjectDestroy()
65 // Tracked object itself removes us from list of trackers
66 wxASSERT(m_pobj
!= NULL
);
78 // Now set new trackable object
81 // Add ourselves to object tracker list
82 wxTrackable
*pt
= static_cast<wxTrackable
*>(pobj
);
88 void AssignCopy(const wxWeakRefStatic
& wr
)
98 #ifndef USE_ONLY_STATIC_WEAKREF
100 template<class T
,bool use_static
>
101 struct wxWeakRefImpl
;
103 // Intermediate class, to select the static case above.
105 struct wxWeakRefImpl
<T
, true> : public wxWeakRefStatic
<T
>
110 // Weak ref implementation when T does not have wxTrackable as known base class
112 struct wxWeakRefImpl
<T
, false> : public wxTrackerNode
116 // Release old object if any
119 // Remove ourselves from object tracker list
120 m_ptbase
->RemoveNode(this);
126 virtual void OnObjectDestroy()
128 // Tracked object itself removes us from list of trackers
129 wxASSERT(m_pobj
!= NULL
);
135 wxWeakRefImpl() : m_pobj(NULL
), m_ptbase(NULL
) { }
137 // Assign receives most derived class here and can use that
138 template <class TDerived
>
139 void Assign( TDerived
* pobj
)
141 AssignHelper( pobj
, wxInt2Type
<wxIsStaticTrackable
<TDerived
>::value
>() );
144 template <class TDerived
>
145 void AssignHelper(TDerived
* pobj
, wxInt2Type
<true>)
147 wxTrackable
*ptbase
= static_cast<wxTrackable
*>(pobj
);
148 DoAssign( pobj
, ptbase
);
152 void AssignHelper(T
* pobj
, wxInt2Type
<false>)
154 // A last way to get a trackable pointer
155 wxTrackable
*ptbase
= dynamic_cast<wxTrackable
*>(pobj
);
158 DoAssign( pobj
, ptbase
);
162 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
167 #endif // RTTI enabled
169 void AssignCopy(const wxWeakRefImpl
& wr
)
171 DoAssign(wr
.m_pobj
, wr
.m_ptbase
);
174 void DoAssign( T
* pobj
, wxTrackable
*ptbase
) {
175 if( m_pobj
==pobj
) return;
178 // Now set new trackable object
181 // Add ourselves to object tracker list
183 ptbase
->AddNode( this );
190 wxTrackable
*m_ptbase
;
193 #endif // #ifndef USE_ONLY_STATIC_WEAKREF
197 // A weak reference to an object of type T, where T has base wxTrackable
198 // (usually statically but if not dynamic_cast<> is tried).
200 class wxWeakRef
: public
201 #ifdef USE_ONLY_STATIC_WEAKREF
204 wxWeakRefImpl
<T
, wxIsStaticTrackable
<T
>::value
!= 0>
208 typedef T element_type
;
213 // Enabling this ctor for VC6 results in mysterious compilation failures in
214 // wx/window.h when assigning wxWindow pointers (FIXME-VC6)
216 // Ctor from the object of this type: this is needed as the template ctor
217 // below is not used by at least g++4 when a literal NULL is used
222 #endif // !__VISUALC6__
224 // When we have the full type here, static_cast<> will always work
225 // (or give a straight compiler error).
226 template <class TDerived
>
227 wxWeakRef(TDerived
* pobj
)
232 // We need this copy ctor, since otherwise a default compiler (binary) copy
233 // happens (if embedded as an object member).
234 wxWeakRef(const wxWeakRef
<T
>& wr
)
236 this->Assign(wr
.get());
239 wxWeakRef
<T
>& operator=(const wxWeakRef
<T
>& wr
)
241 this->AssignCopy(wr
);
245 virtual ~wxWeakRef() { this->Release(); }
247 // Smart pointer functions
248 T
& operator*() const { return *this->m_pobj
; }
249 T
* operator->() const { return this->m_pobj
; }
251 T
* get() const { return this->m_pobj
; }
252 operator T
*() const { return this->m_pobj
; }
258 // Weak ref implementation assign objects are queried for wxTrackable
259 // using dynamic_cast<>
261 class wxWeakRefDynamic
: public wxTrackerNode
264 wxWeakRefDynamic() : m_pobj(NULL
) { }
266 wxWeakRefDynamic(T
* pobj
) : m_pobj(pobj
)
271 wxWeakRefDynamic(const wxWeakRef
<T
>& wr
)
276 virtual ~wxWeakRefDynamic() { Release(); }
278 // Smart pointer functions
279 T
& operator*() const { wxASSERT(m_pobj
); return *m_pobj
; }
280 T
* operator->() const { wxASSERT(m_pobj
); return m_pobj
; }
282 T
* get() const { return m_pobj
; }
283 operator T
* () const { return m_pobj
; }
285 T
* operator = (T
* pobj
) { Assign(pobj
); return m_pobj
; }
287 // Assign from another weak ref, point to same object
288 T
* operator = (const wxWeakRef
<T
> &wr
) { Assign( wr
.get() ); return m_pobj
; }
292 // Release old object if any
295 // Remove ourselves from object tracker list
296 wxTrackable
*pt
= dynamic_cast<wxTrackable
*>(m_pobj
);
298 pt
->RemoveNode(this);
303 virtual void OnObjectDestroy()
305 wxASSERT_MSG(m_pobj
, "tracked object should have removed us itself");
313 if ( m_pobj
== pobj
)
318 // Now set new trackable object
321 // Add ourselves to object tracker list
322 wxTrackable
*pt
= dynamic_cast<wxTrackable
*>(pobj
);
330 // If the object we want to track does not support wxTackable, then
331 // log a message and keep the NULL object pointer.
332 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
340 #endif // RTTI enabled
343 // Provide some basic types of weak references
344 class WXDLLIMPEXP_FWD_BASE wxEvtHandler
;
345 class WXDLLIMPEXP_FWD_CORE wxWindow
;
348 typedef wxWeakRef
<wxEvtHandler
> wxEvtHandlerRef
;
349 typedef wxWeakRef
<wxWindow
> wxWindowRef
;
351 #endif // _WX_WEAKREF_H_