fix doc example typo
[boost.git] / boost / scope_exit.hpp
blobd838dee47bd96f9ce3b8b638124a2eb31e67a6a7
1 // Copyright Alexander Nasonov 2006-2009
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 #ifndef FILE_boost_scope_exit_hpp_INCLUDED
8 #define FILE_boost_scope_exit_hpp_INCLUDED
10 #include <boost/config.hpp>
12 #include <boost/detail/workaround.hpp>
13 #include <boost/preprocessor/cat.hpp>
14 #include <boost/preprocessor/facilities/empty.hpp>
15 #include <boost/preprocessor/punctuation/comma_if.hpp>
16 #include <boost/preprocessor/seq/cat.hpp>
17 #include <boost/preprocessor/seq/for_each_i.hpp>
18 #include <boost/preprocessor/tuple/elem.hpp>
19 #include <boost/typeof/typeof.hpp>
21 #if defined(__GNUC__) && !defined(BOOST_INTEL)
22 # define BOOST_SCOPE_EXIT_AUX_GCC (__GNUC__ * 100 + __GNUC_MINOR__)
23 #else
24 # define BOOST_SCOPE_EXIT_AUX_GCC 0
25 #endif
27 #if BOOST_WORKAROUND(BOOST_SCOPE_EXIT_AUX_GCC, BOOST_TESTED_AT(413))
28 #define BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
29 #endif
31 // Steven Watanabe's trick
32 namespace boost { namespace scope_exit { namespace aux {
34 template<int> struct declare;
36 typedef void* declared;
37 struct undeclared { declared dummy[2]; };
39 template<>
40 struct declare<sizeof(undeclared)>
42 template<int>
43 struct apply
45 declared value;
46 friend void operator>(bool, const apply&) {}
50 template<>
51 struct declare<sizeof(declared)>
53 static const int apply = 0;
55 } } }
57 extern boost::scope_exit::aux::undeclared boost_scope_exit_args; // undefined
60 namespace boost { namespace scope_exit { namespace aux {
62 typedef void (*ref_tag)(int&);
63 typedef void (*val_tag)(int );
65 template<class T, class Tag> struct member;
67 template<class T>
68 struct member<T,ref_tag>
70 T& value;
71 #ifndef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
72 member(T& ref) : value(ref) {}
73 #endif
76 template<class T>
77 struct member<T,val_tag>
79 T value;
80 #ifndef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
81 member(T& val) : value(val) {}
82 #endif
85 template<class T> inline T& deref(T* p, ref_tag) { return *p; }
86 template<class T> inline T& deref(T& r, val_tag) { return r; }
88 template<class T>
89 struct wrapper
91 typedef T type;
94 template<class T> wrapper<T> wrap(T&);
96 } } }
98 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
99 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::scope_exit::aux::wrapper, 1)
101 #define BOOST_SCOPE_EXIT_AUX_GUARD(id) BOOST_PP_CAT(boost_se_guard_, id)
102 #define BOOST_SCOPE_EXIT_AUX_GUARD_T(id) BOOST_PP_CAT(boost_se_guard_t_, id)
103 #define BOOST_SCOPE_EXIT_AUX_PARAMS(id) BOOST_PP_CAT(boost_se_params_, id)
104 #define BOOST_SCOPE_EXIT_AUX_PARAMS_T(id) BOOST_PP_CAT(boost_se_params_t_, id)
106 #define BOOST_SCOPE_EXIT_AUX_TAG(id, i) \
107 BOOST_PP_SEQ_CAT( (boost_se_tag_)(i)(_)(id) )
109 #define BOOST_SCOPE_EXIT_AUX_PARAM(id, i, var) \
110 BOOST_PP_SEQ_CAT( (boost_se_param_)(i)(_)(id) )
112 #define BOOST_SCOPE_EXIT_AUX_PARAM_T(id, i, var) \
113 BOOST_PP_SEQ_CAT( (boost_se_param_t_)(i)(_)(id) )
115 #define BOOST_SCOPE_EXIT_AUX_CAPTURE_T(id, i, var) \
116 BOOST_PP_SEQ_CAT( (boost_se_capture_t_)(i)(_)(id) )
118 #define BOOST_SCOPE_EXIT_AUX_WRAPPED(id, i) \
119 BOOST_PP_SEQ_CAT( (boost_se_wrapped_t_)(i)(_)(id) )
121 #define BOOST_SCOPE_EXIT_AUX_DEREF(id, i, var) \
122 boost::scope_exit::aux::deref(var, (BOOST_SCOPE_EXIT_AUX_TAG(id,i))0)
124 #define BOOST_SCOPE_EXIT_AUX_MEMBER(r, id, i, var) \
125 boost::scope_exit::aux::member< \
126 BOOST_SCOPE_EXIT_AUX_PARAM_T(id,i,var), \
127 BOOST_SCOPE_EXIT_AUX_TAG(id,i) \
128 > BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var);
130 // idty is (id,typename) or (id,BOOST_PP_EMPTY())
131 #define BOOST_SCOPE_EXIT_AUX_ARG_DECL(r, idty, i, var) \
132 BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2,1,idty) \
133 BOOST_SCOPE_EXIT_AUX_PARAMS_T(BOOST_PP_TUPLE_ELEM(2,0,idty)):: \
134 BOOST_SCOPE_EXIT_AUX_PARAM_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var) var
136 #define BOOST_SCOPE_EXIT_AUX_ARG(r, id, i, var) BOOST_PP_COMMA_IF(i) \
137 boost_se_params_->BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var).value
139 #define BOOST_SCOPE_EXIT_AUX_TAG_DECL(r, id, i, var) \
140 typedef void (*BOOST_SCOPE_EXIT_AUX_TAG(id,i))(int var);
143 #ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
145 #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq)
147 #define BOOST_SCOPE_EXIT_AUX_PARAM_INIT(r, id, i, var) \
148 BOOST_PP_COMMA_IF(i) { BOOST_SCOPE_EXIT_AUX_DEREF(id,i,var) }
150 #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq) \
151 = { BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_INIT, id, seq) };
153 #else
155 #define BOOST_SCOPE_EXIT_AUX_CTOR_ARG(r, id, i, var) BOOST_PP_COMMA_IF(i) \
156 BOOST_SCOPE_EXIT_AUX_PARAM_T(id,i,var) & BOOST_PP_CAT(a,i)
158 #define BOOST_SCOPE_EXIT_AUX_MEMBER_INIT(r, id, i, var) BOOST_PP_COMMA_IF(i) \
159 BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var) ( BOOST_PP_CAT(a,i) )
161 #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq) \
162 BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)( \
163 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_CTOR_ARG, id, seq ) ) \
164 : BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER_INIT, id, seq) {}
166 #define BOOST_SCOPE_EXIT_AUX_PARAM_INIT(r, id, i, var) \
167 BOOST_PP_COMMA_IF(i) BOOST_SCOPE_EXIT_AUX_DEREF(id,i,var)
169 #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq) \
170 ( BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_INIT, id, seq) );
172 #endif
174 #if defined(BOOST_TYPEOF_EMULATION)
176 #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
177 struct BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i) \
178 : BOOST_TYPEOF(boost::scope_exit::aux::wrap( \
179 BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var))) \
180 {}; typedef BOOST_PP_TUPLE_ELEM(2,1,idty) \
181 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i)::type \
182 BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
184 #elif defined(BOOST_INTEL)
186 #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
187 typedef BOOST_TYPEOF_KEYWORD( \
188 BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var)) \
189 BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
191 #else
193 #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
194 typedef BOOST_TYPEOF(boost::scope_exit::aux::wrap( \
195 BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var))) \
196 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i); \
197 typedef BOOST_PP_TUPLE_ELEM(2,1,idty) \
198 BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i)::type \
199 BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
201 #endif
203 #define BOOST_SCOPE_EXIT_AUX_PARAM_DECL(r, idty, i, var) \
204 typedef BOOST_SCOPE_EXIT_AUX_CAPTURE_T( \
205 BOOST_PP_TUPLE_ELEM(2,0,idty), i, var) \
206 BOOST_SCOPE_EXIT_AUX_PARAM_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
209 #define BOOST_SCOPE_EXIT_AUX_IMPL(id, seq, ty) \
210 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_TAG_DECL, id, seq) \
211 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL, (id,ty), seq) \
212 struct BOOST_SCOPE_EXIT_AUX_PARAMS_T(id) { \
213 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_DECL, (id,ty), seq)\
214 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER, id, seq) \
215 BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq) \
216 } BOOST_SCOPE_EXIT_AUX_PARAMS(id) BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq)\
217 boost::scope_exit::aux::declare<sizeof(boost_scope_exit_args)> \
218 ::apply<0> boost_scope_exit_args; \
219 boost_scope_exit_args.value = &BOOST_SCOPE_EXIT_AUX_PARAMS(id); \
220 struct BOOST_SCOPE_EXIT_AUX_GUARD_T(id) { \
221 BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)* boost_se_params_; \
222 BOOST_SCOPE_EXIT_AUX_GUARD_T(id) (void* boost_se_params) \
223 : boost_se_params_( \
224 (BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)*)boost_se_params) \
225 {} \
226 ~BOOST_SCOPE_EXIT_AUX_GUARD_T(id)() { boost_se_body( \
227 BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_ARG, id, seq) ); } \
228 static void boost_se_body(BOOST_PP_SEQ_FOR_EACH_I( \
229 BOOST_SCOPE_EXIT_AUX_ARG_DECL, (id,ty), seq) )
231 #if defined(BOOST_MSVC)
233 #define BOOST_SCOPE_EXIT_END } BOOST_SCOPE_EXIT_AUX_GUARD(__COUNTER__) ( \
234 boost_scope_exit_args.value);
236 #define BOOST_SCOPE_EXIT(seq) \
237 BOOST_SCOPE_EXIT_AUX_IMPL(__COUNTER__, seq, BOOST_PP_EMPTY())
239 #else
241 #define BOOST_SCOPE_EXIT_END } BOOST_SCOPE_EXIT_AUX_GUARD(__LINE__) ( \
242 boost_scope_exit_args.value);
244 #define BOOST_SCOPE_EXIT(seq) \
245 BOOST_SCOPE_EXIT_AUX_IMPL(__LINE__, seq, BOOST_PP_EMPTY())
247 #endif
249 #ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
250 #define BOOST_SCOPE_EXIT_TPL(seq) \
251 BOOST_SCOPE_EXIT_AUX_IMPL(__LINE__, seq, typename)
252 #else
253 #define BOOST_SCOPE_EXIT_TPL(seq) BOOST_SCOPE_EXIT(seq)
254 #endif
256 #endif // #ifndef FILE_boost_scope_exit_hpp_INCLUDED