]> git.saurik.com Git - wxWidgets.git/blame - include/wx/weakref.h
VC5 didn't support partial specialization either, check for VC>=7
[wxWidgets.git] / include / wx / weakref.h
CommitLineData
db7035e4
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: wx/weakref.h
3// Purpose: wxWeakRef - Generic weak references for wxWidgets
4// Author: Arne Steinarson
cc6ceca7 5// Created: 27 Dec 07
9dd5ff5b 6// RCS-ID: $Id$
db7035e4
VZ
7// Copyright: (c) 2007 Arne Steinarson
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifndef _WX_WEAKREF_H_
12#define _WX_WEAKREF_H_
13
cc6ceca7 14#include "wx/tracker.h"
db7035e4 15
cc6ceca7
VZ
16#include "wx/meta/convertible.h"
17#include "wx/meta/int2type.h"
18
19template <class T>
20struct wxIsStaticTrackable
21{
22 enum { value = wxConvertibleTo<T, wxTrackable>::value };
23};
24
25// Weak ref implementation when T has wxTrackable as a known base class
26template <class T>
27class wxWeakRefStatic : public wxTrackerNode
28{
29public:
30 wxWeakRefStatic() : m_pobj(NULL) { }
31
32 void Release()
33 {
34 // Release old object if any
35 if ( m_pobj )
36 {
37 // Remove ourselves from object tracker list
38 wxTrackable *pt = static_cast<wxTrackable*>(m_pobj);
39 pt->RemoveNode(this);
40 m_pobj = NULL;
41 }
42 }
43
44protected:
45 void Assign(T* pobj)
46 {
47 if ( m_pobj == pobj )
48 return;
49
50 Release();
51
52 // Now set new trackable object
53 if ( pobj )
54 {
55 // Add ourselves to object tracker list
56 wxTrackable *pt = static_cast<wxTrackable*>(pobj);
57 pt->AddNode(this);
58 m_pobj = pobj;
59 }
60 }
61
42d9ad79 62 void AssignCopy(const wxWeakRefStatic& wr)
cc6ceca7
VZ
63 {
64 Assign( wr.m_pobj );
65 }
66
67 virtual void OnObjectDestroy()
68 {
69 // Tracked object itself removes us from list of trackers
70 wxASSERT( m_pobj!=NULL );
71 m_pobj = NULL;
72 }
73
74 T *m_pobj;
75};
76
77#ifdef HAVE_PARTIAL_SPECIALIZATION
78
79template<class T,bool use_static>
80struct wxWeakRefImpl;
81
82// Intermediate class, to select the static case above.
83template <class T>
84struct wxWeakRefImpl<T, true> : public wxWeakRefStatic<T>
85{
86 enum { value = 1 };
87};
88
89// Weak ref implementation when T does not have wxTrackable as known base class
db7035e4 90template<class T>
cc6ceca7
VZ
91struct wxWeakRefImpl<T, false> : public wxTrackerNode
92{
93 void Release()
94 {
95 // Release old object if any
96 if ( m_pobj )
97 {
98 // Remove ourselves from object tracker list
99 m_ptbase->RemoveNode(this);
100 m_pobj = NULL;
101 m_ptbase = NULL;
102 }
103 }
104
105protected:
106 wxWeakRefImpl() : m_pobj(NULL), m_ptbase(NULL) { }
107
108 // Assign receives most derived class here and can use that
109 template <class TDerived>
110 void Assign( TDerived* pobj )
111 {
112 AssignHelper( pobj, wxInt2Type<wxIsStaticTrackable<TDerived>::value>() );
113 }
114
115 template <class TDerived>
116 void AssignHelper(TDerived* pobj, wxInt2Type<true>)
117 {
118 wxTrackable *ptbase = static_cast<wxTrackable*>(pobj);
119 DoAssign( pobj, ptbase );
120 }
121
122#ifdef HAVE_DYNAMIC_CAST
123 void AssignHelper(T* pobj, wxInt2Type<false>)
124 {
125 // A last way to get a trackable pointer
126 wxTrackable *ptbase = dynamic_cast<wxTrackable*>(pobj);
127 if ( ptbase )
128 {
129 DoAssign( pobj, ptbase );
130 }
131 else
132 {
133 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
134
135 Release();
136 }
137 }
138#endif // HAVE_DYNAMIC_CAST
139
140 void AssignCopy(const wxWeakRefImpl& wr)
141 {
42d9ad79 142 DoAssign(wr.m_pobj, wr.m_ptbase);
cc6ceca7
VZ
143 }
144
145 void DoAssign( T* pobj, wxTrackable *ptbase ) {
146 if( m_pobj==pobj ) return;
147 Release();
148
149 // Now set new trackable object
150 if( pobj )
151 {
152 // Add ourselves to object tracker list
153 wxASSERT( ptbase );
154 ptbase->AddNode( this );
155 m_pobj = pobj;
156 m_ptbase = ptbase;
157 }
158 }
159
160 virtual void OnObjectDestroy()
161 {
162 // Tracked object itself removes us from list of trackers
163 wxASSERT( m_pobj!=NULL );
164 m_pobj = NULL;
165 m_ptbase = NULL;
166 }
167
168 T *m_pobj;
169 wxTrackable *m_ptbase;
170};
171
172#endif // HAVE_PARTIAL_SPECIALIZATION
173
174
175// A weak reference to an object of type T, where T has type wxTrackable
176// (usually statically but if not dynamic_cast<> is tried).
177template <class T>
178class wxWeakRef : public
179#ifdef HAVE_PARTIAL_SPECIALIZATION
180 wxWeakRefImpl<T, wxIsStaticTrackable<T>::value>
181#else
182 wxWeakRefStatic<T>
183#endif
db7035e4
VZ
184{
185public:
cc6ceca7
VZ
186 // Default ctor
187 wxWeakRef() { }
188
189 // When we have the full type here, static_cast<> will always work
190 // (or give a straight compiler error).
191 template <class TDerived>
192 wxWeakRef(TDerived* pobj)
193 {
194 Assign(pobj);
195 }
196
197 template <class TDerived>
198 wxWeakRef<T>& operator=(TDerived* pobj)
199 {
200 Assign(pobj);
201 return *this;
202 }
203
204 wxWeakRef<T>& operator=(const wxWeakRef<T>& wr)
205 {
206 AssignCopy(wr);
207 return *this;
208 }
db7035e4 209
34bfda8a 210 virtual ~wxWeakRef() { this->Release(); }
cc6ceca7
VZ
211
212 // Smart pointer functions
34bfda8a
VZ
213 T& operator*() const { return *this->m_pobj; }
214 T* operator->() const { return this->m_pobj; }
cc6ceca7 215
34bfda8a
VZ
216 T* get() const { return this->m_pobj; }
217 operator T*() const { return get(); }
cc6ceca7
VZ
218};
219
220
221// Weak ref implementation assign objects are queried for wxTrackable
222// using dynamic_cast<>
42d9ad79 223template <class T>
cc6ceca7
VZ
224class wxWeakRefDynamic : public wxTrackerNode
225{
226public:
227 wxWeakRefDynamic() : m_pobj(NULL) { }
1e9192d0 228
cc6ceca7 229 wxWeakRefDynamic(T* pobj) : m_pobj(pobj)
db7035e4
VZ
230 {
231 Assign(pobj);
db7035e4
VZ
232 }
233
cc6ceca7
VZ
234 virtual ~wxWeakRefDynamic() { Release(); }
235
236 // Smart pointer functions
237 T& operator * (){ wxASSERT(this->m_pobj); return *m_pobj; }
238 T* operator -> (){ wxASSERT(this->m_pobj); return m_pobj; }
239 T* operator = (T* pobj) { Assign(pobj); return m_pobj; }
240
241 T* get(){ return this->m_pobj; }
242
243 // operator T* (){ return this->m_pobj; }
244
245 // test for pointer validity: defining conversion to unspecified_bool_type
246 // and not more obvious bool to avoid implicit conversions to integer types
247 typedef T *(wxWeakRef<T>::*unspecified_bool_type)() const;
248 operator unspecified_bool_type() const
db7035e4 249 {
cc6ceca7 250 return m_pobj ? &wxWeakRef<T>::get : NULL;
db7035e4
VZ
251 }
252
cc6ceca7
VZ
253 // Assign from another weak ref, point to same object
254 T* operator = (const wxWeakRef<T> &wr) { Assign( wr.get() ); return this->m_pobj; }
db7035e4 255
cc6ceca7 256 void Release()
db7035e4 257 {
cc6ceca7
VZ
258 // Release old object if any
259 if( m_pobj )
db7035e4
VZ
260 {
261 // Remove ourselves from object tracker list
cc6ceca7 262 wxTrackable *pt = dynamic_cast<wxTrackable*>(m_pobj);
9dd5ff5b
RR
263 wxASSERT(pt);
264 pt->RemoveNode(this);
db7035e4
VZ
265 m_pobj = NULL;
266 }
cc6ceca7
VZ
267 }
268
269protected:
270 void Assign(T *pobj)
271 {
272 if ( m_pobj == pobj )
273 return;
274
275 Release();
db7035e4
VZ
276
277 // Now set new trackable object
278 if ( pobj )
279 {
cc6ceca7
VZ
280 // Add ourselves to object tracker list
281 wxTrackable *pt = dynamic_cast<wxTrackable*>(pobj);
282 if ( pt )
9dd5ff5b 283 {
cc6ceca7 284 pt->AddNode(this);
9dd5ff5b
RR
285 m_pobj = pobj;
286 }
287 else
288 {
cc6ceca7
VZ
289 // If the object we want to track does not support wxTackable, then
290 // log a message and keep the NULL object pointer.
291 wxFAIL_MSG( "Tracked class should inherit from wxTrackable" );
9dd5ff5b 292 }
db7035e4
VZ
293 }
294 }
295
cc6ceca7
VZ
296 virtual void OnObjectDestroy()
297 {
298 wxASSERT_MSG( m_pobj, "tracked object should have removed us itself" );
299
300 m_pobj = NULL;
301 }
302
db7035e4
VZ
303 T *m_pobj;
304};
305
306// Provide some basic types of weak references
db7035e4 307class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
cc6ceca7 308class WXDLLIMPEXP_FWD_BASE wxWindow;
db7035e4 309
db7035e4
VZ
310typedef wxWeakRef<wxEvtHandler> wxEvtHandlerRef;
311typedef wxWeakRef<wxWindow> wxWindowRef;
312
313#endif // _WX_WEAKREF_H_
314