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