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"
16 #include "wx/meta/convertible.h"
17 #include "wx/meta/int2type.h"
20 struct wxIsStaticTrackable
22 enum { value
= wxConvertibleTo
<T
, wxTrackable
>::value
};
25 // Weak ref implementation when T has wxTrackable as a known base class
27 class wxWeakRefStatic
: public wxTrackerNode
30 wxWeakRefStatic() : m_pobj(NULL
) { }
34 // Release old object if any
37 // Remove ourselves from object tracker list
38 wxTrackable
*pt
= static_cast<wxTrackable
*>(m_pobj
);
52 // Now set new trackable object
55 // Add ourselves to object tracker list
56 wxTrackable
*pt
= static_cast<wxTrackable
*>(pobj
);
62 void AssignCopy(const wxWeakRefStatic
& wr
)
67 virtual void OnObjectDestroy()
69 // Tracked object itself removes us from list of trackers
70 wxASSERT( m_pobj
!=NULL
);
78 #if !defined(HAVE_PARTIAL_SPECIALIZATION) || !defined(HAVE_TEMPLATE_OVERLOAD_RESOLUTION)
79 #define USE_STATIC_WEAKREF
83 #ifndef USE_STATIC_WEAKREF
84 template<class T
,bool use_static
>
87 // Intermediate class, to select the static case above.
89 struct wxWeakRefImpl
<T
, true> : public wxWeakRefStatic
<T
>
94 // Weak ref implementation when T does not have wxTrackable as known base class
96 struct wxWeakRefImpl
<T
, false> : public wxTrackerNode
100 // Release old object if any
103 // Remove ourselves from object tracker list
104 m_ptbase
->RemoveNode(this);
111 wxWeakRefImpl() : m_pobj(NULL
), m_ptbase(NULL
) { }
113 // Assign receives most derived class here and can use that
114 template <class TDerived
>
115 void Assign( TDerived
* pobj
)
117 AssignHelper( pobj
, wxInt2Type
<wxIsStaticTrackable
<TDerived
>::value
>() );
120 template <class TDerived
>
121 void AssignHelper(TDerived
* pobj
, wxInt2Type
<true>)
123 wxTrackable
*ptbase
= static_cast<wxTrackable
*>(pobj
);
124 DoAssign( pobj
, ptbase
);
127 #ifdef HAVE_DYNAMIC_CAST
128 void AssignHelper(T
* pobj
, wxInt2Type
<false>)
130 // A last way to get a trackable pointer
131 wxTrackable
*ptbase
= dynamic_cast<wxTrackable
*>(pobj
);
134 DoAssign( pobj
, ptbase
);
138 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
143 #endif // HAVE_DYNAMIC_CAST
145 void AssignCopy(const wxWeakRefImpl
& wr
)
147 DoAssign(wr
.m_pobj
, wr
.m_ptbase
);
150 void DoAssign( T
* pobj
, wxTrackable
*ptbase
) {
151 if( m_pobj
==pobj
) return;
154 // Now set new trackable object
157 // Add ourselves to object tracker list
159 ptbase
->AddNode( this );
165 virtual void OnObjectDestroy()
167 // Tracked object itself removes us from list of trackers
168 wxASSERT( m_pobj
!=NULL
);
174 wxTrackable
*m_ptbase
;
177 #endif // #ifndef USE_STATIC_WEAKREF
181 // A weak reference to an object of type T, where T has type wxTrackable
182 // (usually statically but if not dynamic_cast<> is tried).
184 class wxWeakRef
: public
185 #ifdef USE_STATIC_WEAKREF
188 wxWeakRefImpl
<T
, wxIsStaticTrackable
<T
>::value
>
195 // When we have the full type here, static_cast<> will always work
196 // (or give a straight compiler error).
197 template <class TDerived
>
198 wxWeakRef(TDerived
* pobj
)
203 // We need this copy ctor, since otherwise a default compiler (binary) copy happens
204 wxWeakRef(const wxWeakRef
<T
>& wr
)
209 template <class TDerived
>
210 wxWeakRef
<T
>& operator=(TDerived
* pobj
)
216 wxWeakRef
<T
>& operator=(const wxWeakRef
<T
>& wr
)
222 virtual ~wxWeakRef() { this->Release(); }
224 // Smart pointer functions
225 T
& operator*() const { return *this->m_pobj
; }
226 T
* operator->() const { return this->m_pobj
; }
228 T
* get() const { return this->m_pobj
; }
229 operator T
*() const { return get(); }
233 // Weak ref implementation assign objects are queried for wxTrackable
234 // using dynamic_cast<>
236 class wxWeakRefDynamic
: public wxTrackerNode
239 wxWeakRefDynamic() : m_pobj(NULL
) { }
241 wxWeakRefDynamic(T
* pobj
) : m_pobj(pobj
)
246 virtual ~wxWeakRefDynamic() { Release(); }
248 // Smart pointer functions
249 T
& operator * (){ wxASSERT(this->m_pobj
); return *m_pobj
; }
250 T
* operator -> (){ wxASSERT(this->m_pobj
); return m_pobj
; }
251 T
* operator = (T
* pobj
) { Assign(pobj
); return m_pobj
; }
253 T
* get(){ return this->m_pobj
; }
255 // operator T* (){ return this->m_pobj; }
257 // test for pointer validity: defining conversion to unspecified_bool_type
258 // and not more obvious bool to avoid implicit conversions to integer types
259 typedef T
*(wxWeakRef
<T
>::*unspecified_bool_type
)() const;
260 operator unspecified_bool_type() const
262 return m_pobj
? &wxWeakRef
<T
>::get
: NULL
;
265 // Assign from another weak ref, point to same object
266 T
* operator = (const wxWeakRef
<T
> &wr
) { Assign( wr
.get() ); return this->m_pobj
; }
270 // Release old object if any
273 // Remove ourselves from object tracker list
274 wxTrackable
*pt
= dynamic_cast<wxTrackable
*>(m_pobj
);
276 pt
->RemoveNode(this);
284 if ( m_pobj
== pobj
)
289 // Now set new trackable object
292 // Add ourselves to object tracker list
293 wxTrackable
*pt
= dynamic_cast<wxTrackable
*>(pobj
);
301 // If the object we want to track does not support wxTackable, then
302 // log a message and keep the NULL object pointer.
303 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
308 virtual void OnObjectDestroy()
310 wxASSERT_MSG( m_pobj
, "tracked object should have removed us itself" );
318 // Provide some basic types of weak references
319 class WXDLLIMPEXP_FWD_BASE wxEvtHandler
;
320 class WXDLLIMPEXP_FWD_CORE wxWindow
;
322 typedef wxWeakRef
<wxEvtHandler
> wxEvtHandlerRef
;
323 typedef wxWeakRef
<wxWindow
> wxWindowRef
;
325 #endif // _WX_WEAKREF_H_