]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/scope_exit/doc/scope_exit.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / scope_exit / doc / scope_exit.qbk
1
2 [/ Copyright (C) 2006-2009, 2012 Alexander Nasonov ]
3 [/ Copyright (C) 2012 Lorenzo Caminiti ]
4 [/ Distributed under the Boost Software License, Version 1.0 ]
5 [/ (see accompanying file LICENSE_1_0.txt or a copy at ]
6 [/ http://www.boost.org/LICENSE_1_0.txt) ]
7 [/ Home at http://www.boost.org/libs/scope_exit ]
8
9 [library Boost.ScopeExit
10 [quickbook 1.5]
11 [version 1.1.0]
12 [copyright 2006-2012 Alexander Nasonov, Lorenzo Caminiti]
13 [purpose execute arbitrary code at scope exit]
14 [license
15 Distributed under the Boost Software License, Version 1.0
16 (see accompanying file LICENSE_1_0.txt or a copy at
17 [@http://www.boost.org/LICENSE_1_0.txt])
18 ]
19 [authors
20 [Nasonov, Alexander]
21 [Caminiti <email>lorcaminiti@gmail.com</email>, Lorenzo]
22 ]
23 [category utility]
24 [id scope_exit]
25 [dirname scope_exit]
26 ]
27
28 [def __Introduction__ [link scope_exit.introduction Introduction]]
29 [def __Getting_Started__ [link scope_exit.getting_started Getting Started]]
30 [def __Tutorial__ [link scope_exit.tutorial Tutorial]]
31 [def __No_Variadic_Macros__ [link scope_exit.no_variadic_macros No Variadic Macros]]
32 [def __Reference__ [@reference.html Reference]]
33 [def __Boost_ScopeExit__ [link scope_exit Boost.ScopeExit]]
34 [def __Boost_Lambda__ [@http://www.boost.org/libs/lambda Boost.Lambda]]
35 [def __Boost_Phoenix__ [@http://www.boost.org/libs/phoenix Boost.Phoenix]]
36 [def __Boost_Typeof__ [@http://www.boost.org/libs/typeof Boost.Typeof]]
37 [def __typeof_emulation__ [@http://www.boost.org/libs/typeof type-of emulation]]
38 [def __Boost_Preprocessor__ [@http://www.boost.org/libs/preprocessor Boost.Preprocessor]]
39 [def __Boost_Config__ [@http://www.boost.org/libs/config Boost.Config]]
40 [def __Boost_PointerContainer__ [@http://www.boost.org/libs/ptr_container Boost.PointerContainer]]
41 [def __Boost_Multi_Index__ [@http://www.boost.org/libs/multi_index Boost.Multi-Index]]
42 [def __ScopeGuard__ [@http://www.ddj.com/dept/cpp/184403758 ScopeGuard]]
43 [def __D__ [@http://www.digitalmars.com/d/index.html D]]
44 [def __D_scope_exit__ [@http://www.digitalmars.com/d/2.0/statement.html#ScopeGuardStatement scope(exit)]]
45 [def __RAII__ [@http://www.research.att.com/~bs/glossary.html#Gresource-acquisition-is-initialization RAII]]
46 [def __strong_guarantee__ [@http://www.research.att.com/~bs/glossary.html#Gstrong-guarantee strong guarantee]]
47
48 [import ../test/world.cpp]
49 [import ../test/world_seq.cpp]
50 [import ../test/world_checkpoint.cpp]
51 [import ../test/world_this.cpp]
52 [import ../test/world_void.cpp]
53 [import ../test/world_checkpoint_all.cpp]
54 [import ../test/world_tpl.cpp]
55 [import ../test/same_line.cpp]
56 [import ../example/try_catch.cpp]
57 [import ../example/scope_guard.cpp]
58 [import ../example/world_cxx11_lambda.cpp]
59
60 This library allows to execute arbitrary code when the enclosing scope exits.
61
62 [section Introduction]
63
64 Nowadays, every C++ developer is familiar with the Resource Acquisition Is Initialization (__RAII__) technique.
65 It binds resource acquisition and release to initialization and destruction of a variable that holds the resource.
66 There are times when writing a special class for such a variable is not worth the effort.
67 This is when __Boost_ScopeExit__ comes into play.
68
69 Programmers can put resource acquisition directly in their code and next to it, they can write code that releases the resource using this library.
70 For example (see also [@../../test/world.cpp =world.cpp=]):
71 [footnote
72 Older versions of this library used a __Boost_Preprocessor__ sequence to specify the list of captured variables.
73 While maintaining full backward compatibility, it is now possible to specify the captured variables also using a comma-separated list (which is the preferred syntax).
74 See the __No_Variadic_Macros__ section for more information.
75 ]
76
77 [world]
78
79 [endsect]
80
81 [section Getting Started]
82
83 This section explains how to setup a system to use this library.
84
85 [section This Documentation]
86
87 Programmers should have enough knowledge to use this library after reading the __Introduction__, __Getting_Started__, and __Tutorial__ sections.
88 The __Reference__ section can be consulted at a later point for quick reference.
89 All the other sections of this documentation can be considered optional.
90
91 Some footnotes are marked by the word "*Rationale*".
92 They explain reasons behind decisions made during the design and implementation of this library.
93
94 In most of the examples presented in this documentation, the Boost.Detail/LightweightTest (=boost/detail/lightweight_test.hpp=) macro `BOOST_TEST` is used to check correctness conditions.
95 The `BOOST_TEST` macro is conceptually similar to `assert` but a failure of the checked condition does not abort the program, instead it makes `boost::report_errors` return a non-zero program exit code.
96 [footnote
97 *Rationale.*
98 Using Boost.Detail/LightweightTest allows to add the examples to the library regression tests so to make sure that they always compile and run correctly.
99 ]
100
101 [endsect]
102
103 [section Compilers and Platforms]
104
105 The authors originally developed and tested the library on GNU Compiler Collection (GCC) C++ 3.3, 3.4, 4.1, 4.2, 4.5.3 (with and without C++11 features [^-std=c++0x]), Microsoft Visual C++ (MSVC) 8.0, and Intel 10.1 under Linux, Cygwin, and Windows 7.
106 However, this library should be usable on any compiler that supports __Boost_Typeof__ except:
107
108 * MSVC 7.1 and 8.0 fail to link if a function with __Boost_ScopeExit__ is included by multiple translation units.
109 * GCC 3.3 cannot compile __Boost_ScopeExit__ inside a template (see [@http://lists.boost.org/Archives/boost/2007/02/116235.php] for details).
110
111 See the library [@http://www.boost.org/development/tests/release/developer/scope_exit.html regression test results] for detailed information on supported compilers and platforms.
112 Check the library regression test [@../../test/Jamfile.v2 =Jamfile.v2=] for any special configuration that might be required for a specific compiler.
113
114 [endsect]
115
116 [section Installation]
117
118 This library is composed of header files only.
119 Therefore there is no pre-compiled object file which needs to be installed.
120 Programmers can simply instruct the compiler where to find the library header files (`-I` option on GCC, `/I` option on MSVC, etc) and compile code using the library.
121
122 The library implementation uses __Boost_Typeof__ to automatically deduce the types of the __Boost_ScopeExit__ captured variables (see the __Tutorial__ section).
123 In order to compile code in __typeof_emulation__ mode, all types should be properly registered using `BOOST_TYPEOF_REGISTER_TYPE` and `BOOST_TYPEOF_REGISTER_TEMPLATE`, or appropriate __Boost_Typeof__ headers should be included (see the source code of most examples presented in this documentation).
124
125 [endsect]
126
127 [endsect]
128
129 [section Tutorial]
130
131 This section illustrates how to use this library.
132
133 [section Capturing Variables]
134
135 Imagine that we want to make many modifications to data members of some `world` class in its `world::add_person` member function.
136 We start with adding a new `person` object to a vector of persons:
137
138 void world::add_person(person const& a_person) {
139 bool commit = false;
140
141 persons_.push_back(a_person); // (1) direct action
142 ...
143
144 Some operations down the road may throw an exception and all changes to involved objects should be rolled back.
145 This all-or-nothing semantic is also known as __strong_guarantee__.
146
147 In particular, the last added person must be deleted from `persons_` if the function throws.
148 All we need is to define a delayed action (release of a resource) right after the direct action (resource acquisition).
149 For example (see also [@../../test/world.cpp =world.cpp=]):
150
151 [world]
152
153 The block below point =(1)= is a __Boost_ScopeExit__ declaration.
154 Unlike point =(1)=, an execution of the __Boost_ScopeExit__ body will be delayed until the end of the current scope. In this case it will be executed either after point =(4)= or on any exception.
155 (On various versions of the GCC compiler, it is necessary to use [macroref BOOST_SCOPE_EXIT_TPL] instead of [macroref BOOST_SCOPE_EXIT] within templates, see later in this section for details.)
156
157 The __Boost_ScopeExit__ declaration starts with the [macroref BOOST_SCOPE_EXIT] macro invocation which accepts a comma-separated list of captured variables (a __Boost_Preprocessor__ sequence is also accepted for compilers that do not support variadic macros and for backward compatibility with older versions of this library, see the __No_Variadic_Macros__ section).
158 If a capture starts with the ampersand sign `&`, a reference to the captured variable will be available inside the __Boost_ScopeExit__ body; otherwise, a copy of the variable will be made after the __Boost_ScopeExit__ declaration at point =(1)= and only the copy will be available inside the body (in this case, the captured variable's type must be [@http://www.boost.org/doc/libs/release/doc/html/CopyConstructible.html `CopyConstructible`]).
159
160 In the example above, the variables `commit` and `persons_` are captured by reference because the final value of the `commit` variable should be used to determine whether to execute rollback actions or not, and the action should modify the `persons_` object, not its copy.
161 This is the most common case but passing a variable by value is sometimes useful as well.
162
163 Finally, the end of the __Boost_ScopeExit__ body must be marked by the [macroref BOOST_SCOPE_EXIT_END] macro which must follow the closing curly bracket `}` of the __Boost_ScopeExit__ body.
164
165 [important
166 In order to comply with the [@http://www.stlport.org/doc/exception_safety.html STL exception safety requirements], the __Boost_ScopeExit__ body must never throw (because the library implementation executes the body within a destructor call).
167 This is true for all __Boost_ScopeExit__ macros (including [macroref BOOST_SCOPE_EXIT_TPL] and [macroref BOOST_SCOPE_EXIT_ALL] seen below) on both C++03 and C++11.
168 ]
169
170 Consider a more complex example where `world::add_person` can save intermediate states at some point and roll back to the last saved state.
171 We use `person::evolution_` to store a version of the changes and increment it to cancel all rollback actions associated with those changes.
172 If we pass a current value of `evolution_` stored in the `checkpoint` variable by value, it remains unchanged within the __Boost_ScopeExit__ body so we can compare it with the final value of `evolution_`.
173 If the latter was not incremented since we saved it, the rollback action inside the __Boost_ScopeExit__ body should be executed.
174 For example (see also [@../../test/world_checkpoint.cpp =world_checkpoint.cpp=]):
175
176 [world_checkpoint]
177
178 When multiple __Boost_ScopeExit__ blocks are declared within the same enclosing scope, the __Boost_ScopeExit__ bodies are executed in the reversed order of their declarations.
179
180 [endsect]
181
182 [section Capturing The Object `this`]
183
184 Within a member function, it is also possible to capture the object `this`.
185 However, the special symbol `this_` must be used instead of `this` in the __Boost_ScopeExit__ declaration and body to capture and access the object.
186 For example (see also [@../../test/world_this.cpp =world_this.cpp=]):
187
188 [world_this]
189
190 It is not possible to capture the object `this_` by reference because C++ does not allow to take a reference to `this`.
191 If the enclosing member function is constant then the captured object will also be constant, otherwise the captured object will be mutable.
192
193 [endsect]
194
195 [section Capturing No Variable]
196
197 A __Boost_ScopeExit__ declaration can also capture no variable.
198 In this case, the list of captured variables is replaced by the `void` keyword (similarly to the C++ syntax that allows to declare a function with no parameter using [^['result-type function-name]]`(void)`).
199 [footnote
200 *Rationale.*
201 Unfortunately, it is not possible to simply invoke the __Boost_ScopeExit__ macro with no parameters as in `BOOST_SCOPE_EXIT()` because the C++ preprocessor cannot detect emptiness of a macro parameter when the parameter can start with a non-alphanumeric symbol (which is the case when capturing a variable by reference `&variable`).
202 ]
203 For example, this can be useful when the __Boost_ScopeExit__ body only needs to access global variables (see also [@../../test/world_void.cpp =world_void.cpp=]):
204
205 [world_void]
206
207 (Both compilers with and without variadic macros use this same syntax for capturing no variable, see the __No_Variadic_Macros__ section for more information.)
208
209 [endsect]
210
211 [section Capturing All Variables (C++11 Only)]
212
213 On C++11 compliers, it is also possible to capture all the variables in scope without naming them one-by-one using the special macro [macroref BOOST_SCOPE_EXIT_ALL] instead of [macroref BOOST_SCOPE_EXIT].
214 [footnote
215 *Rationale.*
216 The [macroref BOOST_SCOPE_EXIT_ALL] macro is only defined on C++11 compilers for which the __Boost_Config__ macro `BOOST_NO_CXX11_LAMBDAS` is not defined.
217 Using [macroref BOOST_SCOPE_EXIT_ALL] on C++03 compilers for which `BOOST_NO_CXX11_LAMBDAS` is defined will generate (possibly cryptic) compiler errors.
218 Note that a new macro [macroref BOOST_SCOPE_EXIT_ALL] needed to be introduced instead of reusing [macroref BOOST_SCOPE_EXIT] because `BOOST_SCOPE_EXIT(&)` and `BOOST_SCOPE_EXIT(=)` cannot be distinguished from `BOOST_SCOPE_EXIT(void)` or `BOOST_SCOPE_EXIT(this_)` using the C++ preprocessor given that the symbols `&` and `=` are neither prefxied nor postfixed by alphanumeric tokens (this is not an issue for [macroref BOOST_SCOPE_EXIT_ALL] which always has the non-alphanumeric `&` or `=` as the first capture so the first capture tokens are simply never compared with neither `void` nor `this_` for this macro).
219 ]
220
221 Following the same syntax adopted by C++11 lambda functions, the [macroref BOOST_SCOPE_EXIT_ALL] macro accepts a comma-separated list of captures which must start with either `&` or `=` to capture all variables in scope respectively by reference or by value (note that no variable name is specified by these leading captures).
222 Additional captures of specific variables can follow the leading `&` or `=` and they will override the default reference or value captures.
223 For example (see also [@../../test/world_checkpoint_all.cpp =world_checkpoint_all.cpp=]):
224
225 [world_checkpoint_all]
226
227 The first __Boost_ScopeExit__ declaration captures all variables in scope by reference but the variable `checkpoint` and the object `this` which are explicitly captured by value (in particular, `p` and `persons_` are implicitly captured by reference here).
228 The second __Boost_ScopeExit__ declaration instead captures all variables in scope by value but `p` which is explicitly captured by reference (in particular, `checkpoint`, `prev_id`, and `this` are implicitly captured by value here).
229
230 Note that the [macroref BOOST_SCOPE_EXIT_ALL] macro follows the C++11 lambda function syntax which is unfortunately different from the [macroref BOOST_SCOPE_EXIT] macro syntax.
231 In particular:
232
233 # The [macroref BOOST_SCOPE_EXIT_ALL] macro cannot capture data members without capturing the object `this` while that is not the case for [macroref BOOST_SCOPE_EXIT].
234 [footnote
235 At present, there seems to be some discussion to allow C++11 lambda functions to capture data members without capturing the object `this`.
236 If the C++11 standard were changed to allow this, the [macroref BOOST_SCOPE_EXIT_ALL] macro syntax could be extended to be a superset of the [macroref BOOST_SCOPE_EXIT] macro while keeping full backward compatibility.
237 ]
238 # The [macroref BOOST_SCOPE_EXIT_ALL] macro captures the object in scope using `this` instead of `this_`.
239 [footnote
240 On compilers that support the use of the `typename` outside templates as allowed by the C++11 standard, [macroref BOOST_SCOPE_EXIT_ALL] can use both `this` and `this_` to capture the object in scope (notably, this is not the case for the MSVC 10.0 compiler).
241 ]
242 # The [macroref BOOST_SCOPE_EXIT_ALL] body is terminated by a semicolon `;` instead than by the [macroref BOOST_SCOPE_EXIT_END] macro.
243
244 If programmers define the configuration macro [macroref BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS] then the [macroref BOOST_SCOPE_EXIT] macro implementation will use C++11 lamda functions and the [macroref BOOST_SCOPE_EXIT] macro will follow the same syntax of [macroref BOOST_SCOPE_EXIT_ALL] macro, which is the C++11 lambda function syntax.
245 However, [macroref BOOST_SCOPE_EXIT] will no longer be backward compatible and older code using [macroref BOOST_SCOPE_EXIT] might no longer compile (if data members were explicitly captured).
246
247 [endsect]
248
249 [section Template Workaround (GCC)]
250
251 Various versions of the GCC compiler do not compile [macroref BOOST_SCOPE_EXIT] inside templates (see the __Reference__ section for more information).
252 As a workaround, [macroref BOOST_SCOPE_EXIT_TPL] should be used instead of [macroref BOOST_SCOPE_EXIT] in these cases.
253 [footnote
254 *Rationale.*
255 GCC versions compliant with C++11 do not present this issue and given that [macroref BOOST_SCOPE_EXIT_ALL] is only available on C++11 compilers, there is no need for a `BOOST_SCOPE_EXIT_ALL_TPL` macro.
256 ]
257 The [macroref BOOST_SCOPE_EXIT_TPL] macro has the exact same syntax of [macroref BOOST_SCOPE_EXIT].
258 For example (see also [@../../test/world_tpl.cpp =world_tpl.cpp=]):
259
260 [world_tpl]
261
262 It is recommended to always use [macroref BOOST_SCOPE_EXIT_TPL] within templates so to maximize portability among different compilers.
263
264 [endsect]
265
266 [section Same Line Expansions]
267
268 In general, it is not possible to expand the [macroref BOOST_SCOPE_EXIT], [macroref BOOST_SCOPE_EXIT_TPL], [macroref BOOST_SCOPE_EXIT_END], and [macroref BOOST_SCOPE_EXIT_ALL] macros multiple times on the same line.
269 [footnote
270 *Rationale.*
271 The library macros internally use `__LINE__` to generate unique identifiers.
272 Therefore, if the same macro is expanded more than on time on the same line, the generated identifiers will no longer be unique and the code will not compile.
273 (This restriction does not apply to MSVC and other compilers that provide the non-standard `__COUNTER__` macro.)
274 ]
275
276 Therefore, this library provides additional macros [macroref BOOST_SCOPE_EXIT_ID], [macroref BOOST_SCOPE_EXIT_ID_TPL], [macroref BOOST_SCOPE_EXIT_END_ID], and [macroref BOOST_SCOPE_EXIT_ALL_ID] which can be expanded multiple times on the same line as long as programmers specify a unique identifiers as the macros' first parameters.
277 The unique identifier can be any token (not just numeric) that can be concatenated by the C++ preprocessor (e.g., `scope_exit_number_1_at_line_123`).
278 [footnote
279 Because there are restrictions on the set of tokens that the C++ preprocessor can concatenate and because not all compilers correctly implement these restrictions, it is in general recommended to specify unique identifiers as a combination of alphanumeric tokens.
280 ]
281
282 The [macroref BOOST_SCOPE_EXIT_ID], [macroref BOOST_SCOPE_EXIT_ID_TPL], and [macroref BOOST_SCOPE_EXIT_ALL_ID] macros accept a capture list using the exact same syntax as [macroref BOOST_SCOPE_EXIT] and [macroref BOOST_SCOPE_EXIT_ALL] respectively.
283 For example (see also [@../../test/same_line.cpp =same_line.cpp=]):
284
285 [same_line]
286
287 As shown by the example above, the [macroref BOOST_SCOPE_EXIT_ID], [macroref BOOST_SCOPE_EXIT_ID_TPL], [macroref BOOST_SCOPE_EXIT_END_ID], and [macroref BOOST_SCOPE_EXIT_ALL_ID] macros are especially useful when it is necessary to invoke them multiple times within user-defined macros (because the C++ preprocessor expands all nested macros on the same line).
288
289 [endsect]
290
291 [endsect]
292
293 [section:alternatives Annex: Alternatives]
294
295 This section presents some alternative and related work to __Boost_ScopeExit__.
296
297 [heading Try-Catch]
298
299 This is an example of using a badly designed `file` class.
300 An instance of `file` does not close the file in its destructor, a programmer is expected to call the `close` member function explicitly.
301 For example (see also [@../../example/try_catch.cpp =try_catch.cpp=]):
302
303 [try_catch_bad]
304
305 Note the following issues with this approach:
306
307 # The `passwd` object is defined outside of the `try` block because this object is required inside the `catch` block to close the file.
308 # The `passwd` object is not fully constructed until after the `open`
309 member function returns.
310 # If opening throws, the `passwd.close()` should not be called, hence the call to `passwd.is_open()`.
311
312 The __Boost_ScopeExit__ approach does not have any of these issues.
313 For example (see also [@../../example/try_catch.cpp =try_catch.cpp=]):
314
315 [try_catch_good]
316
317 [heading RAII]
318
319 __RAII__ is absolutely perfect for the `file` class introduced above.
320 Use of a properly designed `file` class would look like:
321
322 try {
323 file passwd("/etc/passwd");
324 // ...
325 } catch(...) {
326 std::clog << "could not get user info" << std::endl;
327 throw;
328 }
329
330 However, using __RAII__ to build up a __strong_guarantee__ could introduce a lot of non-reusable __RAII__ types.
331 For example:
332
333 persons_.push_back(a_person);
334 pop_back_if_not_commit pop_back_if_not_commit_guard(commit, persons_);
335
336 The `pop_back_if_not_commit` class is either defined out of the scope or as a local class:
337
338 class pop_back_if_not_commit {
339 bool commit_;
340 std::vector<person>& vec_;
341 // ...
342 ~pop_back_if_not_commit() {
343 if(!commit_) vec_.pop_back();
344 }
345 };
346
347 In some cases __strong_guarantee__ can be accomplished with standard utilities:
348
349 std::auto_ptr<Person> superman_ptr(new superman());
350 persons_.push_back(superman_ptr.get());
351 superman_ptr.release(); // persons_ successfully took ownership
352
353 Or with specialized containers such as __Boost_PointerContainer__ or __Boost_Multi_Index__.
354
355 [heading Scope Guards]
356
357 Imagine that a new currency rate is introduced before performing a transaction (see also []):
358
359 [scope_guard_decl]
360
361 If the transaction does not complete, the currency must be erased from `rates`.
362 This can be done with __ScopeGuard__ and __Boost_Lambda__ (or __Boost_Phoenix__):
363
364 using namespace boost::lambda;
365
366 ON_BLOCK_EXIT(
367 if_(currency_rate_inserted && !_1) [
368 bind(
369 static_cast<
370 std::map<std::string, double>::size_type
371 (std::map<std::string, double>::*)(std::string const&)
372 >(&std::map<std::string, double>::erase)
373 , &rates
374 , currency
375 )
376 ]
377 , boost::cref(commit)
378 );
379
380 // ...
381
382 commit = true;
383
384 Note the following issues with this approach:
385
386 # __Boost_Lambda__ expressions are hard to write correctly (e.g., overloaded functions must be explicitly casted, as demonstrated in the example above).
387 # The condition in the `if_` expression refers to `commit` variable indirectly through the `_1` placeholder reducing readability.
388 # Setting a breakpoint inside `if_[...]` requires in-depth knowledge of __Boost_Lambda__ and debugging techniques.
389
390 This code will look much better with C++11 lambdas:
391
392 ON_BLOCK_EXIT(
393 [currency_rate_inserted, &commit, &rates, &currency]() {
394 if(currency_rate_inserted && !commit) rates.erase(currency);
395 }
396 );
397
398 // ...
399
400 commit = true;
401
402 With __Boost_ScopeExit__ we can simply do the following (see also [@../../example/scope_guard.cpp =scope_guard.cpp=]):
403
404 [scope_guard_exit]
405
406 [heading The D Programming Language]
407
408 __Boost_ScopeExit__ is similar to __D_scope_exit__ feature built into the __D__ programming language.
409
410 A curious reader may notice that the library does not implement `scope(success)` and `scope(failure)` of the __D__ language.
411 Unfortunately, these are not possible in C++ because failure or success conditions cannot be determined by calling `std::uncaught_exception` (see [@http://www.gotw.ca/gotw/047.htm Guru of the Week #47] for details about `std::uncaught_exception` and if it has any good use at all).
412 However, this is not a big problem because these two __D__'s constructs can be expressed in terms of __D_scope_exit__ and a `bool commit` variable (similarly to some examples presented in the __Tutorial__ section).
413
414 [heading C++11 Lambdas]
415
416 Using C++11 lambdas, it is relatively easy to implement the __Boost_ScopeExit__ construct.
417 For example (see also [@../../example/world_cxx11_lambda.cpp =world_cxx11_lambda.cpp=]):
418
419 [world_cxx11_lambda]
420
421 However, this library allows to program the __Boost_ScopeExit__ construct in a way that is portable between C++03 and C++11 compilers.
422
423 [endsect]
424
425 [section:no_variadic_macros Annex: No Variadic Macros]
426
427 This section presents an alternative syntax for compilers without variadic macro support.
428
429 [heading Sequence Syntax]
430
431 Most modern compilers support variadic macros (notably, these include GCC, MSVC, and all C++11 compilers).
432 [footnote
433 A C++ compiler does not support variadic macros if the __Boost_Config__ macro `BOOST_NO_CXX11_VARIADIC_MACROS` is defined for that compiler.
434 ]
435 However, in the rare case that programmers need to use this library on a complier without variaidc macros, this library also allows to specify the capture list using a __Boost_Preprocessor__ sequence where tokens are separated by round parenthesis `()`:
436
437 (capture1) (capture2) ... // All compilers.
438
439 Instead of the comma-separated list that we have seen so far which requires variadic macros:
440
441 capture1, capture2, ... // Only compilers with variadic macros.
442
443 For example, the following syntax is accepted on all compilers with and without variadic macros (see also [@../../test/world_seq.cpp =world_seq.cpp=] and [@../../test/world.cpp =world.cpp=]):
444
445 [table
446 [ [Boost.Preprocessor Sequence (All Compilers)] [Comma-Separated List (Variadic Macros Only)] ]
447 [ [[world_seq]] [[world]] ]
448 ]
449
450 Note how the same macros accept both syntaxes on compilers with variadic macros and only the __Boost_Preprocessor__ sequence syntax on compilers without variadic macros.
451 Older versions of this library used to only support the __Boost_Preprocessor__ sequence syntax so this syntax is supported also for backward compatibility.
452 However, in the current version of this library and on compilers with variadic macros, the comma-separated syntax is preferred because it is more readable.
453
454 Finally, an empty capture list is always specified using `void` on compilers with and without variaidc macros (see also [@../../test/world_void.cpp =world_void.cpp=]):
455
456 [world_void]
457
458 [heading Examples]
459
460 For reference, the following is a list of most of the examples presented in this documentation reprogrammed using the __Boost_Preprocessor__ sequence syntax instead of comma-separated lists (in alphabetic order):
461
462 [table
463 [ [Files] ]
464 [ [[@../../test/same_line_seq.cpp =same_line_seq.cpp=]] ]
465 [ [[@../../example/scope_guard_seq.cpp =scope_guard_seq.cpp=]] ]
466 [ [[@../../example/try_catch_seq.cpp =try_catch_seq.cpp=]] ]
467 [ [[@../../test/world_checkpoint_all_seq.cpp =world_checkpoint_all_seq.cpp=]] ]
468 [ [[@../../test/world_checkpoint_seq.cpp =world_checkpoint_seq.cpp=]] ]
469 [ [[@../../test/world_this_seq.cpp =world_this_seq.cpp=]] ]
470 [ [[@../../test/world_tpl_seq.cpp =world_tpl_seq.cpp=]] ]
471 ]
472
473 [endsect]
474
475 [xinclude reference.xml]
476
477 [section Acknowledgements]
478
479 Alexander Nasonov is the original library author.
480
481 Lorenzo Caminiti added variadic macro support, capture of the object `this_`, empty captures using `void`, and `BOOST_SCOPE_EXIT_ALL`.
482
483 Thanks to the following people (in chronological order):
484
485 Maxim Yegorushkin for sharing code where he used a local struct to clean up resources;
486
487 Andrei Alexandrescu for pointing out the __D_scope_exit__ construct of the __D__ programming language;
488
489 Pavel Vozenilek and Maxim Yanchenko for reviews of early drafts of the library;
490
491 Steven Watanabe for his valuable ideas;
492
493 Jody Hagins for good comments that helped to significantly improve the documentation;
494
495 Richard Webb for testing the library on MSVC compiler;
496
497 Adam Butcher for a workaround to error C2355 when deducing the type of `this` on some MSVC versions.
498
499 [endsect]
500