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
);
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 // RTTI enabled
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>
209 typedef T element_type
;
214 // Enabling this ctor for VC6 results in mysterious compilation failures in
215 // wx/window.h when assigning wxWindow pointers (FIXME-VC6)
217 // Ctor from the object of this type: this is needed as the template ctor
218 // below is not used by at least g++4 when a literal NULL is used
223 #endif // !__VISUALC6__
225 // When we have the full type here, static_cast<> will always work
226 // (or give a straight compiler error).
227 template <class TDerived
>
228 wxWeakRef(TDerived
* pobj
)
233 // We need this copy ctor, since otherwise a default compiler (binary) copy
234 // happens (if embedded as an object member).
235 wxWeakRef(const wxWeakRef
<T
>& wr
)
240 wxWeakRef
<T
>& operator=(const wxWeakRef
<T
>& wr
)
246 virtual ~wxWeakRef() { this->Release(); }
248 // Smart pointer functions
249 T
& operator*() const { return *this->m_pobj
; }
250 T
* operator->() const { return this->m_pobj
; }
252 T
* get() const { return this->m_pobj
; }
253 operator T
*() const { return this->m_pobj
; }
259 // Weak ref implementation assign objects are queried for wxTrackable
260 // using dynamic_cast<>
262 class wxWeakRefDynamic
: public wxTrackerNode
265 wxWeakRefDynamic() : m_pobj(NULL
) { }
267 wxWeakRefDynamic(T
* pobj
) : m_pobj(pobj
)
272 wxWeakRefDynamic(const wxWeakRef
<T
>& wr
)
277 virtual ~wxWeakRefDynamic() { Release(); }
279 // Smart pointer functions
280 T
& operator*() const { wxASSERT(m_pobj
); return *m_pobj
; }
281 T
* operator->() const { wxASSERT(m_pobj
); return m_pobj
; }
283 T
* get() const { return m_pobj
; }
284 operator T
* () const { return m_pobj
; }
286 T
* operator = (T
* pobj
) { Assign(pobj
); return m_pobj
; }
288 // Assign from another weak ref, point to same object
289 T
* operator = (const wxWeakRef
<T
> &wr
) { Assign( wr
.get() ); return m_pobj
; }
293 // Release old object if any
296 // Remove ourselves from object tracker list
297 wxTrackable
*pt
= dynamic_cast<wxTrackable
*>(m_pobj
);
299 pt
->RemoveNode(this);
304 virtual void OnObjectDestroy()
306 wxASSERT_MSG(m_pobj
, "tracked object should have removed us itself");
314 if ( m_pobj
== pobj
)
319 // Now set new trackable object
322 // Add ourselves to object tracker list
323 wxTrackable
*pt
= dynamic_cast<wxTrackable
*>(pobj
);
331 // If the object we want to track does not support wxTackable, then
332 // log a message and keep the NULL object pointer.
333 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
341 #endif // RTTI enabled
344 // Provide some basic types of weak references
345 class WXDLLIMPEXP_FWD_BASE wxEvtHandler
;
346 class WXDLLIMPEXP_FWD_CORE wxWindow
;
349 typedef wxWeakRef
<wxEvtHandler
> wxEvtHandlerRef
;
350 typedef wxWeakRef
<wxWindow
> wxWindowRef
;
352 #endif // _WX_WEAKREF_H_