]> git.saurik.com Git - wxWidgets.git/blob - include/wx/scopeguard.h
Applied patch [ 803473 ] wxListCtrl header height bugfix
[wxWidgets.git] / include / wx / scopeguard.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/scopeguard.h
3 // Purpose: declares wxwxScopeGuard and related macros
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 03.07.2003
7 // RCS-ID: $Id$
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 /*
13 Acknowledgements: this header is heavily based on (well, almost the exact
14 copy of) wxScopeGuard.h by Andrei Alexandrescu and Petru Marginean published
15 in December 2000 issue of C/C++ Users Journal.
16 */
17
18 #ifndef _WX_SCOPEGUARD_H_
19 #define _WX_SCOPEGUARD_H_
20
21 #include "wx/defs.h"
22
23 // ----------------------------------------------------------------------------
24 // helpers
25 // ----------------------------------------------------------------------------
26
27 namespace wxPrivate
28 {
29 // in the original implementation this was a member template function of
30 // ScopeGuardImplBase but gcc 2.8 which is still used for OS/2 doesn't
31 // support member templates and so we must make it global
32 template <typename ScopeGuardImpl>
33 void OnScopeExit(ScopeGuardImpl& guard)
34 {
35 if ( !guard.WasDismissed() )
36 {
37 // we're called from ScopeGuardImpl dtor and so we must not throw
38 #if wxUSE_EXCEPTIONS
39 try
40 #endif // wxUSE_EXCEPTIONS
41 {
42 guard.Execute();
43 }
44 #if wxUSE_EXCEPTIONS
45 catch ( ... )
46 {
47 }
48 #endif // wxUSE_EXCEPTIONS
49 }
50 }
51
52 // just to avoid the warning about unused variables
53 template <typename T>
54 void Use(const T& WXUNUSED(t))
55 {
56 }
57 } // namespace wxPrivate
58
59 // ============================================================================
60 // wxScopeGuard for functions and functors
61 // ============================================================================
62
63 // ----------------------------------------------------------------------------
64 // wxScopeGuardImplBase: used by wxScopeGuardImpl[0..N] below
65 // ----------------------------------------------------------------------------
66
67 class wxScopeGuardImplBase
68 {
69 public:
70 wxScopeGuardImplBase() : m_wasDismissed(false) { }
71
72 void Dismiss() const { m_wasDismissed = true; }
73
74 // for OnScopeExit() only we can't make it friend, unfortunately)!
75 bool WasDismissed() const { return m_wasDismissed; }
76
77 protected:
78 ~wxScopeGuardImplBase() { }
79
80 wxScopeGuardImplBase(const wxScopeGuardImplBase& other)
81 : m_wasDismissed(other.m_wasDismissed)
82 {
83 other.Dismiss();
84 }
85
86 // must be mutable for copy ctor to work
87 mutable bool m_wasDismissed;
88
89 private:
90 wxScopeGuardImplBase& operator=(const wxScopeGuardImplBase&);
91 };
92
93 // ----------------------------------------------------------------------------
94 // wxScopeGuardImpl0: scope guard for actions without parameters
95 // ----------------------------------------------------------------------------
96
97 template <typename F>
98 class wxScopeGuardImpl0 : public wxScopeGuardImplBase
99 {
100 public:
101 static wxScopeGuardImpl0<F> MakeGuard(F fun)
102 {
103 return wxScopeGuardImpl0<F>(fun);
104 }
105
106 ~wxScopeGuardImpl0() { wxPrivate::OnScopeExit(*this); }
107
108 void Execute() { m_fun(); }
109
110 protected:
111 wxScopeGuardImpl0(F fun) : m_fun(fun) { }
112
113 F m_fun;
114
115 wxScopeGuardImpl0& operator=(const wxScopeGuardImpl0&);
116 };
117
118 template <typename F>
119 inline wxScopeGuardImpl0<F> wxMakeGuard(F fun)
120 {
121 return wxScopeGuardImpl0<F>::MakeGuard(fun);
122 }
123
124 // ----------------------------------------------------------------------------
125 // wxScopeGuardImpl1: scope guard for actions with 1 parameter
126 // ----------------------------------------------------------------------------
127
128 template <typename F, typename P1>
129 class wxScopeGuardImpl1 : public wxScopeGuardImplBase
130 {
131 public:
132 static wxScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
133 {
134 return wxScopeGuardImpl1<F, P1>(fun, p1);
135 }
136
137 ~wxScopeGuardImpl1() { wxPrivate::OnScopeExit(*this); }
138
139 void Execute() { m_fun(m_p1); }
140
141 protected:
142 wxScopeGuardImpl1(F fun, P1 p1) : m_fun(fun), m_p1(p1) { }
143
144 F m_fun;
145 const P1 m_p1;
146
147 wxScopeGuardImpl1& operator=(const wxScopeGuardImpl1&);
148 };
149
150 template <typename F, typename P1>
151 inline wxScopeGuardImpl1<F, P1> wxMakeGuard(F fun, P1 p1)
152 {
153 return wxScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
154 }
155
156 // ----------------------------------------------------------------------------
157 // wxScopeGuardImpl2: scope guard for actions with 2 parameters
158 // ----------------------------------------------------------------------------
159
160 template <typename F, typename P1, typename P2>
161 class wxScopeGuardImpl2 : public wxScopeGuardImplBase
162 {
163 public:
164 static wxScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
165 {
166 return wxScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
167 }
168
169 ~wxScopeGuardImpl2() { wxPrivate::OnScopeExit(*this); }
170
171 void Execute() { m_fun(m_p1, m_p2); }
172
173 protected:
174 wxScopeGuardImpl2(F fun, P1 p1, P2 p2) : m_fun(fun), m_p1(p1), m_p2(p2) { }
175
176 F m_fun;
177 const P1 m_p1;
178 const P2 m_p2;
179
180 wxScopeGuardImpl2& operator=(const wxScopeGuardImpl2&);
181 };
182
183 template <typename F, typename P1, typename P2>
184 inline wxScopeGuardImpl2<F, P1, P2> wxMakeGuard(F fun, P1 p1, P2 p2)
185 {
186 return wxScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
187 }
188
189 // ============================================================================
190 // wxScopeGuards for object methods
191 // ============================================================================
192
193 // ----------------------------------------------------------------------------
194 // wxObjScopeGuardImpl0
195 // ----------------------------------------------------------------------------
196
197 template <class Obj, typename MemFun>
198 class wxObjScopeGuardImpl0 : public wxScopeGuardImplBase
199 {
200 public:
201 static wxObjScopeGuardImpl0<Obj, MemFun>
202 MakeObjGuard(Obj& obj, MemFun memFun)
203 {
204 return wxObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
205 }
206
207 ~wxObjScopeGuardImpl0() { wxPrivate::OnScopeExit(*this); }
208
209 void Execute() { (m_obj.*m_memfun)(); }
210
211 protected:
212 wxObjScopeGuardImpl0(Obj& obj, MemFun memFun)
213 : m_obj(obj), m_memfun(memFun) { }
214
215 Obj& m_obj;
216 MemFun m_memfun;
217 };
218
219 template <class Obj, typename MemFun>
220 inline wxObjScopeGuardImpl0<Obj, MemFun> wxMakeObjGuard(Obj& obj, MemFun memFun)
221 {
222 return wxObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
223 }
224
225 template <class Obj, typename MemFun, typename P1>
226 class wxObjScopeGuardImpl1 : public wxScopeGuardImplBase
227 {
228 public:
229 static wxObjScopeGuardImpl1<Obj, MemFun, P1>
230 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
231 {
232 return wxObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
233 }
234
235 ~wxObjScopeGuardImpl1() { wxPrivate::OnScopeExit(*this); }
236
237 void Execute() { (m_obj.*m_memfun)(m_p1); }
238
239 protected:
240 wxObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1)
241 : m_obj(obj), m_memfun(memFun), m_p1(p1) { }
242
243 Obj& m_obj;
244 MemFun m_memfun;
245 const P1 m_p1;
246 };
247
248 template <class Obj, typename MemFun, typename P1>
249 inline wxObjScopeGuardImpl1<Obj, MemFun, P1>
250 wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
251 {
252 return wxObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
253 }
254
255 template <class Obj, typename MemFun, typename P1, typename P2>
256 class wxObjScopeGuardImpl2 : public wxScopeGuardImplBase
257 {
258 public:
259 static wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>
260 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
261 {
262 return wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
263 }
264
265 ~wxObjScopeGuardImpl2() { wxPrivate::OnScopeExit(*this); }
266
267 void Execute() { (m_obj.*m_memfun)(m_p1, m_p2); }
268
269 protected:
270 wxObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2)
271 : m_obj(obj), m_memfun(memFun), m_p1(p1), m_p2(p2) { }
272
273 Obj& m_obj;
274 MemFun m_memfun;
275 const P1 m_p1;
276 const P2 m_p2;
277 };
278
279 template <class Obj, typename MemFun, typename P1, typename P2>
280 inline wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>
281 wxMakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
282 {
283 return wxObjScopeGuardImpl2<Obj, MemFun, P1, P2>::
284 MakeObjGuard(obj, memFun, p1, p2);
285 }
286
287 // ============================================================================
288 // public stuff
289 // ============================================================================
290
291 // wxScopeGuard is just a reference, see the explanation in CUJ article
292 typedef const wxScopeGuardImplBase& wxScopeGuard;
293
294 // when an unnamed scope guard is needed, the macros below may be used
295 //
296 // NB: the original code has a single (and much nicer) ON_BLOCK_EXIT macro
297 // but this results in compiler warnings about unused variables and I
298 // didn't find a way to work around this other than by having different
299 // macros with different names
300 #define ON_BLOCK_EXIT0(f) \
301 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeGuard(f); \
302 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
303
304 #define ON_BLOCK_EXIT_OBJ0(o, m) \
305 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeObjGuard(o, m); \
306 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
307
308 #define ON_BLOCK_EXIT1(f, p1) \
309 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeGuard(f, p1); \
310 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
311
312 #define ON_BLOCK_EXIT_OBJ1(o, m, p1) \
313 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeObjGuard(o, m, p1); \
314 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
315
316 #define ON_BLOCK_EXIT2(f, p1, p2) \
317 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeGuard(f, p1, p2); \
318 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
319
320 #define ON_BLOCK_EXIT_OBJ2(o, m, p1, p2) \
321 wxScopeGuard wxMAKE_UNIQUE_NAME(scopeGuard) = wxMakeObjGuard(o, m, p1, p2); \
322 wxPrivate::Use(wxMAKE_UNIQUE_NAME(scopeGuard))
323
324 #endif // _WX_SCOPEGUARD_H_
325