Changeset 77030


Ignore:
Timestamp:
Feb 15, 2012, 1:19:41 AM (6 years ago)
Author:
Lorenzo Caminiti
Message:

Updating ScopeExit? docs, examples, and tests after supporting variadics (with full backward compatibility), this capture (this_), no capture (void), and C++11 extensions.

Location:
trunk/libs/scope_exit
Files:
24 added
12 deleted
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/libs/scope_exit/doc

    • Property svn:ignore set to
      reference.xml
  • trunk/libs/scope_exit/doc/Jamfile.v2

    r63146 r77030  
    11
    2 # Copyright 2006 Alexander Nasonov.
    3 # Distributed under the Boost Software License, Version 1.0. (See accompanying
    4 # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
     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
    58
    6 using quickbook ;
     9import quickbook ;
     10using boostbook ;
    711
    8 xml scope_exit : scope_exit.qbk ;
    9 boostbook standalone : scope_exit
    10         :
    11         # Path for links to Boost:
    12         <xsl:param>boost.root=../../../..
     12doxygen reference
     13    :   ../../../boost/scope_exit.hpp
     14    :   <reftitle>"Reference"
     15        <doxygen:param>PREDEFINED="DOXYGEN"
     16        <doxygen:param>QUIET=YES
     17        <doxygen:param>WARN_IF_UNDOCUMENTED=NO
     18        <doxygen:param>HIDE_UNDOC_MEMBERS=YES
     19        <doxygen:param>HIDE_UNDOC_CLASSES=YES
     20        <doxygen:param>ALIASES=" Params=\"<b>Parameters:</b> <table border="0">\" Param{2}=\"<tr><td><b><tt>\\1</tt></b></td><td>\\2</td></tr>\" EndParams=\"</table>\" Returns=\"<b>Returns:</b>\" Note=\"<b>Note:</b>\" Warning=\"<b>Warning:</b>\" See=\"<b>See:</b>\" RefSect{1}=\"\\xmlonly<link linkend='scope_exit.\\1'>\\1</link>\\endxmlonly\" RefSectId{2}=\"\\xmlonly<link linkend='scope_exit.\\1'>\\2</link>\\endxmlonly\" RefClass{1}=\"\\xmlonly<computeroutput><classname alt='\\1'>\\1</classname></computeroutput>\\endxmlonly\" RefFunc{1}=\"\\xmlonly<computeroutput><functionname alt='\\1'>\\1</functionname></computeroutput>\\endxmlonly\" RefMacro{1}=\"\\xmlonly<computeroutput><macroname alt='\\1'>\\1</macroname></computeroutput>\\endxmlonly\" "
     21    ;
     22
     23xml qbk : scope_exit.qbk : <dependency>reference ;
     24
     25boostbook doc : qbk
     26    :   <xsl:param>boost.root=../../../..
     27        <xsl:param>boost.defaults=Boost
    1328        <format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/scope_exit/doc/html
    14         ;
     29    ;
    1530
  • trunk/libs/scope_exit/doc/html

    • Property svn:ignore set to
      doc_HTML.manifest
  • trunk/libs/scope_exit/doc/html/index.html

    r63769 r77030  
    22<head>
    33<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
    4 <title>Chapter&#160;1.&#160;Boost.ScopeExit</title>
     4<title>Chapter&#160;1.&#160;Boost.ScopeExit 1.1.0</title>
    55<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
    6 <meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
    7 <link rel="home" href="index.html" title="Chapter&#160;1.&#160;Boost.ScopeExit">
    8 <link rel="next" href="scope_exit/tutorial.html" title="Tutorial">
     6<meta name="generator" content="DocBook XSL Stylesheets V1.76.1">
     7<link rel="home" href="index.html" title="Chapter&#160;1.&#160;Boost.ScopeExit 1.1.0">
     8<link rel="next" href="scope_exit/Getting_Started.html" title="Getting Started">
    99</head>
    1010<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
     
    1818</tr></table>
    1919<hr>
    20 <div class="spirit-nav"><a accesskey="n" href="scope_exit/tutorial.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
     20<div class="spirit-nav"><a accesskey="n" href="scope_exit/Getting_Started.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
    2121<div class="chapter">
    2222<div class="titlepage"><div>
    2323<div><h2 class="title">
    24 <a name="scope_exit"></a>Chapter&#160;1.&#160;Boost.ScopeExit</h2></div>
     24<a name="scope_exit"></a>Chapter&#160;1.&#160;Boost.ScopeExit 1.1.0</h2></div>
    2525<div><div class="author"><h3 class="author">
    2626<span class="firstname">Alexander</span> <span class="surname">Nasonov</span>
    2727</h3></div></div>
    28 <div><p class="copyright">Copyright &#169; 2006 -2009 Alexander Nasonov</p></div>
     28<div><div class="author"><h3 class="author">
     29<span class="firstname">Lorenzo</span> <span class="surname">Caminiti <code class="email">&lt;<a class="email" href="mailto:lorcaminiti@gmail.com">lorcaminiti@gmail.com</a>&gt;</code></span>
     30</h3></div></div>
     31<div><p class="copyright">Copyright &#169; 2006-2012 Alexander Nasonov, Lorenzo Caminiti</p></div>
    2932<div><div class="legalnotice">
    30 <a name="id759689"></a><p>
    31         Distributed under the Boost Software License, Version 1.0. (See accompanying
    32         file LICENSE_1_0.txt or copy at &lt;ulink url="http://www.boost.org/LICENSE_1_0.txt"&gt;
    33         http://www.boost.org/LICENSE_1_0.txt &lt;/ulink&gt;)
     33<a name="scope_exit.legal"></a><p>
     34        Distributed under the Boost Software License, Version 1.0 (see accompanying
     35        file LICENSE_1_0.txt or a copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
    3436      </p>
    3537</div></div>
     
    3840<p><b>Table of Contents</b></p>
    3941<dl>
    40 <dt><span class="section"><a href="index.html#scope_exit.intro"> Introduction</a></span></dt>
    41 <dt><span class="section"><a href="scope_exit/tutorial.html"> Tutorial</a></span></dt>
    42 <dt><span class="section"><a href="scope_exit/alternatives.html"> Alternatives</a></span></dt>
    43 <dt><span class="section"><a href="scope_exit/compilers.html"> Supported Compilers</a></span></dt>
    44 <dt><span class="section"><a href="scope_exit/conf.html"> Configuration</a></span></dt>
    45 <dt><span class="section"><a href="scope_exit/ref.html"> Reference</a></span></dt>
    46 <dt><span class="section"><a href="scope_exit/acknowledge.html"> Acknowledge</a></span></dt>
     42<dt><span class="section"><a href="index.html#scope_exit.introduction">Introduction</a></span></dt>
     43<dt><span class="section"><a href="scope_exit/Getting_Started.html">Getting Started</a></span></dt>
     44<dd><dl>
     45<dt><span class="section"><a href="scope_exit/Getting_Started.html#scope_exit.Getting_Started.compilers_and_platforms">Compilers
     46      and Platforms</a></span></dt>
     47<dt><span class="section"><a href="scope_exit/Getting_Started.html#scope_exit.Getting_Started.installation">Installation</a></span></dt>
     48</dl></dd>
     49<dt><span class="section"><a href="scope_exit/Tutorial.html">Tutorial</a></span></dt>
     50<dd><dl>
     51<dt><span class="section"><a href="scope_exit/Tutorial.html#scope_exit.Tutorial.capturing_variables">Capturing Variables</a></span></dt>
     52<dt><span class="section"><a href="scope_exit/Tutorial.html#scope_exit.Tutorial.capturing_the_object__this_">Capturing
     53      The Object <code class="computeroutput"><span class="keyword">this</span></code></a></span></dt>
     54<dt><span class="section"><a href="scope_exit/Tutorial.html#scope_exit.Tutorial.capturing_no_variable">Capturing
     55      No Variable</a></span></dt>
     56<dt><span class="section"><a href="scope_exit/Tutorial.html#scope_exit.Tutorial.capturing_all_variables__c__11_only_">Capturing
     57      All Variables (C++11 Only)</a></span></dt>
     58<dt><span class="section"><a href="scope_exit/Tutorial.html#scope_exit.Tutorial.gcc_template_workaround">GCC Template
     59      Workaround</a></span></dt>
     60</dl></dd>
     61<dt><span class="section"><a href="reference.html">Reference</a></span></dt>
     62<dd><dl><dt><span class="section"><a href="reference.html#header.boost.scope_exit_hpp">Header &lt;boost/scope_exit.hpp&gt;</a></span></dt></dl></dd>
     63<dt><span class="section"><a href="scope_exit/Alternatives.html">Annex: Alternatives</a></span></dt>
     64<dt><span class="section"><a href="scope_exit/No_Variadic_Macros.html">Annex: No Variadic Macros</a></span></dt>
     65<dt><span class="section"><a href="scope_exit/Acknowledgements.html">Acknowledgements</a></span></dt>
    4766</dl>
    4867</div>
    49 <div class="section">
     68<p>
     69    This library allows to execute arbitrary code when the enclosing scope exits.
     70  </p>
     71<div class="section scope_exit_introduction">
    5072<div class="titlepage"><div><div><h2 class="title" style="clear: both">
    51 <a name="scope_exit.intro"></a> Introduction</h2></div></div></div>
     73<a name="scope_exit.introduction"></a><a class="link" href="index.html#scope_exit.introduction" title="Introduction">Introduction</a>
     74</h2></div></div></div>
    5275<p>
    53       Nowadays, every C++ developer is familiar with <a href="http://www.research.att.com/~bs/glossary.html#Gresource-acquisition-is-initialization" target="_top">RAII</a>
     76      Nowadays, every C++ developer is familiar with the Resource Acquisition Is
     77      Initialization (<a href="http://www.research.att.com/~bs/glossary.html#Gresource-acquisition-is-initialization" target="_top">RAII</a>)
    5478      technique. It binds resource acquisition and release to initialization and
    5579      destruction of a variable that holds the resource. But there are times when
    56       writing a special class for such variable is not worth the effort.
     80      writing a special class for such variable is not worth the effort. This is
     81      when the <a class="link" href="index.html" title="Chapter&#160;1.&#160;Boost.ScopeExit 1.1.0">Boost.ScopeExit</a> comes into play.
    5782    </p>
    5883<p>
    59       This is when <a class="link" href="index.html" title="Chapter&#160;1.&#160;Boost.ScopeExit">ScopeExit</a> macro comes into play.
    60       You put resource acquisition directly in your code and next to it you write
    61       a code that releases the resource.
     84      Programmers can put resource acquisition directly in their code and next to
     85      it, they can write code that releases the resource using this library. For
     86      example: <sup>[<a name="scope_exit.introduction.f0" href="#ftn.scope_exit.introduction.f0" class="footnote">1</a>]</sup>
    6287    </p>
    6388<p>
    64       Read <a class="link" href="scope_exit/tutorial.html" title="Tutorial">Tutorial</a> to find out how to
    65       write programs with <a class="link" href="index.html" title="Chapter&#160;1.&#160;Boost.ScopeExit">ScopeExit</a> or jump straight
    66       to the <a class="link" href="scope_exit/ref.html" title="Reference">Reference</a> section.
     89</p>
     90<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">world</span><span class="special">::</span><span class="identifier">add_person</span><span class="special">(</span><span class="identifier">person</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">a_person</span><span class="special">)</span> <span class="special">{</span>
     91    <span class="keyword">bool</span> <span class="identifier">commit</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span>
     92
     93    <span class="identifier">persons_</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">a_person</span><span class="special">);</span>           <span class="comment">// (1) direct action</span>
     94    <span class="comment">// Following block is executed when the enclosing scope exits.</span>
     95    <span class="identifier">BOOST_SCOPE_EXIT</span><span class="special">(&amp;</span><span class="identifier">commit</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">persons_</span><span class="special">)</span> <span class="special">{</span>
     96        <span class="keyword">if</span><span class="special">(!</span><span class="identifier">commit</span><span class="special">)</span> <span class="identifier">persons_</span><span class="special">.</span><span class="identifier">pop_back</span><span class="special">();</span>    <span class="comment">// (2) rollback action</span>
     97    <span class="special">}</span> <span class="identifier">BOOST_SCOPE_EXIT_END</span>
     98
     99    <span class="comment">// ...                                  // (3) other operations</span>
     100
     101    <span class="identifier">commit</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>                          <span class="comment">// (4) disable rollback actions</span>
     102<span class="special">}</span>
     103</pre>
     104<p>
    67105    </p>
     106<p>
     107      Read the <a class="link" href="scope_exit/Tutorial.html" title="Tutorial">Tutorial</a> section to find
     108      out how to write programs with <a class="link" href="index.html" title="Chapter&#160;1.&#160;Boost.ScopeExit 1.1.0">Boost.ScopeExit</a>
     109      or jump to the <a href="reference.html" target="_top">Reference</a> section.
     110    </p>
     111</div>
     112<div class="footnotes">
     113<br><hr width="100" align="left">
     114<div class="footnote"><p><sup>[<a id="ftn.scope_exit.introduction.f0" href="#scope_exit.introduction.f0" class="para">1</a>] </sup>
     115        Older versions of this library used a <a href="http://www.boost.org/libs/preprocessor" target="_top">Boost.Preprocessor</a>
     116        sequence to specify the list of captured variables. While maintaining full
     117        backward compatibility, it is now possible to specify the captured variables
     118        also as a comma-separated list (which is the preferred syntax). See the
     119        <a class="link" href="scope_exit/No_Variadic_Macros.html" title="Annex: No Variadic Macros">No Variadic Macros</a> section
     120        for more details.
     121      </p></div>
    68122</div>
    69123</div>
    70124<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
    71 <td align="left"><p><small>Last revised: July 08, 2010 at 22:36:27 GMT</small></p></td>
     125<td align="left"><p><small>Last revised: February 14, 2012 at 16:13:19 GMT</small></p></td>
    72126<td align="right"><div class="copyright-footer"></div></td>
    73127</tr></table>
    74128<hr>
    75 <div class="spirit-nav"><a accesskey="n" href="scope_exit/tutorial.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
     129<div class="spirit-nav"><a accesskey="n" href="scope_exit/Getting_Started.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
    76130</body>
    77131</html>
  • trunk/libs/scope_exit/doc/scope_exit.qbk

    r53101 r77030  
     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
    19[library Boost.ScopeExit
    2     [copyright 2006-2009 Alexander Nasonov]
     10    [quickbook 1.5]
     11    [version 1.1.0]
     12    [copyright 2006-2012 Alexander Nasonov, Lorenzo Caminiti]
    313    [purpose execute arbitrary code at scope exit]
    414    [license
    5         Distributed under the Boost Software License, Version 1.0.
    6         (See accompanying file LICENSE_1_0.txt or copy at
    7         <ulink url="http://www.boost.org/LICENSE_1_0.txt">
    8             http://www.boost.org/LICENSE_1_0.txt
    9         </ulink>)
     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])
    1018    ]
    11     [authors [Nasonov, Alexander]]
     19    [authors
     20        [Nasonov, Alexander]
     21        [Caminiti <email>lorcaminiti@gmail.com</email>, Lorenzo]
     22    ]
    1223    [category utility]
    1324    [id scope_exit]
     
    1526]
    1627
    17 [/  Images   ]
    18 
    19 [def _note_                         [$images/note.png]]
    20 
    21 [/  Links   ]
    22 
    23 [def _scope_exit_ [link scope_exit ScopeExit]]
    24 [def _Tutorial_ [link scope_exit.tutorial Tutorial]]
    25 [def _Reference_ [link scope_exit.ref Reference]]
    26 [def _lambda_ [@../../../../libs/lambda/index.html Boost.Lambda]]
    27 [def _typeof_ [@../../../../libs/typeof/index.html Boost.Typeof]]
    28 [def _typeof_emulation_ [@../../../../libs/typeof/index.html typeof emulation]]
    29 [def _typeof_REGISTER_TYPE_ [@../../../../doc/html/typeof/refe.html#typeof.regtype BOOST_TYPEOF_REGISTER_TYPE]]
    30 [def _typeof_REGISTER_TEMPLATE_ [@../../../../doc/html/typeof/refe.html#typeof.regtemp BOOST_TYPEOF_REGISTER_TEMPLATE]]
    31 [def _pp_ [@../../../../libs/preprocessor/index.html Boost.Preprocessor]]
    32 [def _pp_seq_ [@../../../../libs/preprocessor/index.html Boost.Preprocessor sequence]]
    33 [def _ptr_container_ [@../../../../libs/ptr_container/doc/ptr_container.html Boost Pointer Container Library]]
    34 [def _multi_index_ [@../../../../libs/multi_index/doc/index.html Boost Multi-Index Containers Library]]
    35 [def _scope_guard_ [@http://www.ddj.com/dept/cpp/184403758 ScopeGuard]]
    36 [def _D_ [@http://www.digitalmars.com/d/index.html D]]
    37 [def _D_scope_exit_ [@http://www.digitalmars.com/d/2.0/statement.html#ScopeGuardStatement scope(exit)]]
    38 [def _RAII_ [@http://www.research.att.com/~bs/glossary.html#Gresource-acquisition-is-initialization RAII]]
    39 [def _strong_guarantee_ [@http://www.research.att.com/~bs/glossary.html#Gstrong-guarantee strong guarantee]]
    40 
    41 [section:intro Introduction]
    42 
    43 Nowadays, every C++ developer is familiar with _RAII_ technique.
    44 It binds resource acquisition and release to initialization and
    45 destruction of a variable that holds the resource. But there are
    46 times when writing a special class for such variable is not worth
    47 the effort.
    48 
    49 This is when _scope_exit_ macro comes into play. You put resource
    50 acquisition directly in your code and next to it you write a code
    51 that releases the resource.
    52 
    53 Read _Tutorial_ to find out how to write programs with
    54 _scope_exit_ or jump straight to the _Reference_ section.
    55 
    56 [endsect]
    57 
    58 [section:tutorial Tutorial]
    59 
    60 Imagine that you want to make many modifications to data members
    61 of the `World` class in the `World::addPerson` function.
    62 You start with adding a new `Person` object to a vector of persons:
    63 
    64         void World::addPerson(Person const& person) {
    65             bool commit = false;
    66             m_persons.push_back(person);  // (1) direct action
    67 
    68 Some operation down the road may throw an exception and all changes
    69 to involved objects should be rolled back. This all-or-nothing semantic
    70 is also known as _strong_guarantee_.
    71 
    72 In particular, last added person must be deleted from `m_persons` when
    73 the function throws. All you need is to define a delayed action (release
    74 of a resource) right after the direct action (resource acquisition):
    75 
    76         void World::addPerson(Person const& aPerson) {
    77             bool commit = false;
    78             m_persons.push_back(aPerson);  // (1) direct action
    79             BOOST_SCOPE_EXIT( (&commit)(&m_persons) )
    80             {
    81                 if(!commit)
    82                     m_persons.pop_back(); // (2) rollback action
    83             } BOOST_SCOPE_EXIT_END
    84        
    85             // ...                        // (3) other operations
    86            
    87             commit = true;                // (4) turn all rollback actions into no-op
    88         }
    89 
    90 The block below point `(1)` is a _scope_exit_ declaration.
    91 Unlike point `(1)`, an execution of the _scope_exit_ body will be
    92 delayed until the end of the current scope. In this case it will be
    93 executed either after point `(4)` or on any exception.
    94 
    95 The _scope_exit_ declaration starts with `BOOST_SCOPE_EXIT` macro
    96 invocation which accepts _pp_seq_ of captured variables. If a capture
    97 starts with the ampersand sign `&`, a reference to the captured variable
    98 will be available inside the _scope_exit_ body; otherwise, a copy of the
    99 variable will be made after the point `(1)` and only the copy will be
    100 available inside the body.
    101 
    102 In the example above, variables `commit` and `m_persons` are passed
    103 by reference because the final value of the `commit` variable should
    104 be used to determine whether to execute rollback action or not and
    105 the action should modify the `m_persons` object, not its copy.
    106 This is a most common case but passing a variable by value is
    107 sometimes useful as well.
    108 
    109 Consider a more complex case where `World::addPerson` can save intermediate
    110 states at some points and roll back to the last saved state. You can
    111 use `Person::m_evolution` to store a version of changes and increment it
    112 to cancel all rollback actions associated with those changes.
    113 
    114 If you pass a current value of `m_evolution` stored in the `checkpoint`
    115 variable by value, it will remain unchanged until the end of aa  scope
    116 and you can compare it with the final value of the `m_evolution`.
    117 If the latter wasn't incremented since you saved it, the rollback action
    118 inside the block should be executed:
    119 
    120         void World::addPerson(Person const& aPerson) {
    121             m_persons.push_back(aPerson);
    122        
    123             // This block must be no-throw
    124             Person& person = m_persons.back();
    125             Person::evolution_t checkpoint = person.m_evolution;
    126        
    127             BOOST_SCOPE_EXIT( (checkpoint)(&person)(&m_persons) )
    128             {
    129                 if(checkpoint == person.m_evolution)
    130                     m_persons.pop_back();
    131             } BOOST_SCOPE_EXIT_END
    132        
     28[def __Tutorial__ [link scope_exit.Tutorial Tutorial]]
     29[def __No_Variadic_Macros__ [link scope_exit.No_Variadic_Macros No Variadic Macros]]
     30[def __Reference__ [@reference.html Reference]]
     31[def __Boost_ScopeExit__ [link scope_exit Boost.ScopeExit]]
     32[def __Boost_Lambda__ [@http://www.boost.org/libs/lambda Boost.Lambda]]
     33[def __Boost_Phoenix__ [@http://www.boost.org/libs/phoenix Boost.Phoenix]]
     34[def __Boost_Typeof__ [@http://www.boost.org/libs/typeof Boost.Typeof]]
     35[def __typeof_emulation__ [@http://www.boost.org/libs/typeof type-of emulation]]
     36[def __BOOST_TYPEOF_REGISTER_TYPE__ [@http://www.boost.org/libs/typeof/refe.html#typeof.regtype BOOST_TYPEOF_REGISTER_TYPE]]
     37[def __BOOST_TYPEOF_REGISTER_TEMPLATE__ [@http://www.boost.org/libs/typeof/refe.html#typeof.regtemp BOOST_TYPEOF_REGISTER_TEMPLATE]]
     38[def __Boost_Preprocessor__ [@http://www.boost.org/libs/preprocessor Boost.Preprocessor]]
     39[def __Boost_PointerContainer__ [@http://www.boost.org/libs/ptr_container Boost.PointerContainer]]
     40[def __Boost_Multi_Index__ [@http://www.boost.org/libs/multi_index Boost.Multi-Index]]
     41[def __ScopeGuard__ [@http://www.ddj.com/dept/cpp/184403758 ScopeGuard]]
     42[def __D__ [@http://www.digitalmars.com/d/index.html D]]
     43[def __D_scope_exit__ [@http://www.digitalmars.com/d/2.0/statement.html#ScopeGuardStatement scope(exit)]]
     44[def __RAII__ [@http://www.research.att.com/~bs/glossary.html#Gresource-acquisition-is-initialization RAII]]
     45[def __strong_guarantee__ [@http://www.research.att.com/~bs/glossary.html#Gstrong-guarantee strong guarantee]]
     46
     47[import ../test/world.cpp]
     48[import ../test/world_seq.cpp]
     49[import ../test/world_checkpoint.cpp]
     50[import ../test/world_this.cpp]
     51[import ../test/world_void.cpp]
     52[import ../test/world_checkpoint_all.cpp]
     53[import ../test/world_tpl.cpp]
     54[import ../test/world_lambda.cpp]
     55[import ../example/try_catch.cpp]
     56[import ../example/scope_guard.cpp]
     57
     58This library allows to execute arbitrary code when the enclosing scope exits.
     59
     60[section Introduction]
     61
     62Nowadays, every C++ developer is familiar with the Resource Acquisition Is Initialization (__RAII__) technique.
     63It binds resource acquisition and release to initialization and destruction of a variable that holds the resource.
     64But there are times when writing a special class for such variable is not worth the effort.
     65This is when the __Boost_ScopeExit__ comes into play.
     66
     67Programmers can put resource acquisition directly in their code and next to it, they can write code that releases the resource using this library.
     68For example:
     69[footnote
     70Older versions of this library used a __Boost_Preprocessor__ sequence to specify the list of captured variables.
     71While maintaining full backward compatibility, it is now possible to specify the captured variables also as a comma-separated list (which is the preferred syntax).
     72See the __No_Variadic_Macros__ section for more details.
     73]
     74
     75[world]
     76
     77Read the __Tutorial__ section to find out how to write programs with __Boost_ScopeExit__ or jump to the __Reference__ section.
     78
     79[endsect]
     80
     81[section:Getting_Started Getting Started]
     82
     83This section explains how to setup a system to use this library.
     84
     85[section Compilers and Platforms]
     86
     87The library should be usable on any compiler that supports __Boost_Typeof__ except:
     88
     89* MSVC 7.1 and 8.0 fail to link if a function with __Boost_ScopeExit__ is included by multiple translation units.
     90Furthermore, on MSVC 7.1 and 8.0 it is possible to capture the object `this_` only with native __Boost_Typeof__ (and not in __typeof_emulation__ mode).
     91* GCC 3.3 cannot compile __Boost_ScopeExit__ inside a template (see [@http://lists.boost.org/Archives/boost/2007/02/116235.php] for more details).
     92
     93The authors tested the library on GCC 3.3, 3.4, 4.1, 4.2, 4.5.3 (with and without C++11 features [^-std=c++0x]), MSVC 8.0, and Intel 10.1 under Linux, Cygwin, and Windows 7.
     94
     95[endsect]
     96
     97[section Installation]
     98
     99This library is composed of header files only.
     100Therefore there is no pre-compiled object file which needs to be installed.
     101Programmers 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.
     102
     103The library implementation uses __Boost_Typeof__ to automatically deduce the types of the __Boost_ScopeExit__ captured variables (see the __Tutorial__ section).
     104In order to compile code in __typeof_emulation__ mode, all types should be properly registered with __BOOST_TYPEOF_REGISTER_TYPE__ or __BOOST_TYPEOF_REGISTER_TEMPLATE__ macros, or appropriate __Boost_Typeof__ headers should be included.
     105
     106[endsect]
     107
     108[endsect]
     109
     110[section:Tutorial Tutorial]
     111
     112This section illustrates how to use this library.
     113
     114[section Capturing Variables]
     115
     116Imagine that we want to make many modifications to data members of some `world` class in its `world::add_person` member function.
     117We start with adding a new `person` object to a vector of persons:
     118
     119    void world::add_person(person const& a_person) {
     120        bool commit = false;
     121
     122        persons_.push_back(a_person);           // (1) direct action
     123        ...
     124
     125Some operations down the road may throw an exception and all changes to involved objects should be rolled back.
     126This all-or-nothing semantic is also known as __strong_guarantee__.
     127
     128In particular, the last added person must be deleted from `persons_` if the function throws.
     129All we need is to define a delayed action (release of a resource) right after the direct action (resource acquisition).
     130For example (see also [@../../test/world.cpp =world.cpp=]):
     131
     132[world]
     133
     134The block below point =(1)= is a __Boost_ScopeExit__ declaration.
     135Unlike 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.
     136(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.)
     137
     138The __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 here for compilers that do not support variadic macros and for backward compatibility with older versions of this library, see the __No_Variadic_Macros__ section).
     139If 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 `CopyConstructible`).
     140
     141In 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.
     142This is the most common case but passing a variable by value is sometimes useful as well.
     143
     144Finally, 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.
     145On C++11 it is also possible (but not required) to use a semi-column `;` instead of the [macroref BOOST_SCOPE_EXIT_END] macro.
     146[footnote
     147The macro [macroref BOOST_SCOPE_EXIT_END] can still be used on C++11 to write portable code that can be used on both C++03 and C++11 compilers.
     148Using `;` instead of [macroref BOOST_SCOPE_EXIT_END] on C++03 compilers will generate a (possibly cryptic) compiler error.
     149]
     150
     151[important
     152In order to comply with the STL exception safety requirements, the __Boost_ScopeExit__ body must never throw (because the library implementation executes the body within a destructor).
     153This is true for all __Boost_ScopeExit__ macros (including [macroref BOOST_SCOPE_EXIT_TPL] and [macroref BOOST_SCOPE_EXIT_ALL]) on both C++03 and C++11.
     154]
     155
     156Consider a more complex example where `world::add_person` can save intermediate states at some point and roll back to the last saved state.
     157We use `person::evolution_` to store a version of the changes and increment it to cancel all rollback actions associated with those changes.
     158If 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_`.
     159If the latter was not incremented since we saved it, the rollback action inside the __Boost_ScopeExit__ body should be executed.
     160For example (see also [@../../test/world_checkpoint.cpp =world_checkpoint.cpp=]):
     161
     162[world_checkpoint]
     163
     164When multiple __Boost_ScopeExit__ blocks are declared within the same enclosing scope, the __Boost_ScopeExit__ bodies are executed in the reversed order of their declarations.
     165
     166[endsect]
     167
     168[section Capturing The Object `this`]
     169
     170Within a member function, it is also possible to capture the object `this`.
     171However, the special symbol `this_` must be used instead of `this` in the __Boost_ScopeExit__ declaration and body to capture and access the object.
     172For example (see also [@../../test/world_this.cpp =world_this.cpp=]):
     173
     174[world_this_]
     175
     176On C++11, it is possible (but not required) to directly use `this` instead of the special symbol `this_`.
     177[footnote
     178The special symbol `this_` can still be used on C++11 to write portable code that can be used on both C++03 and C++11 compilers.
     179Unfortunately, using `this` instead of `this_` on C++03 compilers leads to undefined behaviour (it will likely generate a compiler error but that is not guaranteed).
     180]
     181For example (see also [@../../test/world_this.cpp =world_this.cpp=]):
     182
     183[world_this]
     184
     185It is never possible to capture the object `this_` (or `this`) by reference because C++ does not allow to take a reference to `this`.
     186If the enclosing member function is constant then the captured object will also be constant, otherwise the captured object will be mutable.
     187
     188[endsect]
     189
     190[section Capturing No Variable]
     191
     192It is possible to declare __Boost_ScopeExit__ code that captures no variable.
     193In 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)`).
     194[footnote
     195*Rationale.*
     196Unfortunately, it is not possible to simply invoke the __Boost_ScopeExit__ macro with no parameters `BOOST_SCOPE_EXIT()` because the 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`).
     197]
     198For 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=]):
     199
     200[world_void]
     201
     202This same syntax is supported for both compilers with and without variadic macro support.
     203
     204[endsect]
     205
     206[section Capturing All Variables (C++11 Only)]
     207
     208On 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].
     209[footnote
     210*Rationale.*
     211The [macroref BOOST_SCOPE_EXIT_ALL] macro is only defined on C++11 compilers.
     212Using [macroref BOOST_SCOPE_EXIT_ALL] on C++03 compilers will generate a (possibly cryptic) compiler error.
     213Note 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(=)` could not be distinguished from `BOOST_SCOPE_EXIT(void)` or `BOOST_SCOPE_EXIT(this_)` using the preprocessor because the symbols `&` and `=` are neither prefxied or postfixed by alphanumeric tokens (this is not an issue for [macroref BOOST_SCOPE_EXIT_ALL] which always has `&` or `=` as the first capture so the first capture token is never compared with neither `void` or `this_` for this macro).
     214]
     215
     216Following the same syntax adopted by C++11 lambdas, 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).
     217Additional captures of specific variables can follow the leading `&` or `=` and they will override the default reference or value captures.
     218For example (see also [@../../test/world_checkpoint_all.cpp =world_checkpoint_all.cpp=]):
     219
     220[world_checkpoint_all]
     221
     222The first __Boost_ScopeExit__ declaration captures all variables in scope by reference but `checkpoint` and `this_` which are explicitly captured by value (in particular, `p` and `persons_` are captured by reference).
     223The second __Boost_ScopeExit__ declaration instead captures all variables in scope by value but `p` which is captured by reference (in particular, `checkpoint`, `prev_id`, and `this` are captured by value).
     224
     225[endsect]
     226
     227[section GCC Template Workaround]
     228
     229Various versions of the GCC compiler do not compile [macroref BOOST_SCOPE_EXIT] inside templates (see the __Reference__ section for more information).
     230As a workaround, [macroref BOOST_SCOPE_EXIT_TPL] should be used instead of [macroref BOOST_SCOPE_EXIT] in these cases:
     231[footnote
     232GCC 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.
     233]
     234
     235[world_tpl]
     236
     237The [macroref BOOST_SCOPE_EXIT_TPL] macro has the exact same syntax of [macroref BOOST_SCOPE_EXIT].
     238
     239[endsect]
     240
     241[endsect]
     242
     243[xinclude reference.xml]
     244
     245[section:Alternatives Annex: Alternatives]
     246
     247This section presents some alternatives and work related to __Boost_ScopeExit__.
     248
     249[h5 Try-Catch]
     250
     251This is an example of using a badly designed `file` class.
     252An instance of `file` does not close the file in its destructor, a programmer is expected to call the `close` member function explicitly.
     253For example (see also [@../../example/try_catch.cpp =try_catch.cpp=]):
     254
     255[try_catch_bad]
     256
     257Note the following issues with this approach:
     258
     259* The `passwd` object is defined outside of the `try` block because this object is required inside the `catch` block to close the file.
     260* The `passwd` object is not fully constructed until after the `open`
     261member function returns.
     262* If opening throws, the `passwd.close()` should not be called, hence the call to `passwd.is_open()`.
     263
     264The __Boost_ScopeExit__ approach does not have any of these issues.
     265For example (see also [@../../example/try_catch.cpp =try_catch.cpp=]):
     266
     267[try_catch_good]
     268
     269[h5 RAII]
     270
     271__RAII__ is absolutely perfect for the `file` class introduced above.
     272Use of a properly designed `file` class would look like:
     273
     274        try {
     275            file passwd("/etc/passwd");
    133276            // ...
    134        
    135             checkpoint = ++person.m_evolution;
    136        
    137             // Assign new id to the person
    138             World::id_t const prev_id = person.m_id;
    139             person.m_id = m_next_id++;
    140             BOOST_SCOPE_EXIT( (checkpoint)(&person)(&m_next_id)(prev_id) )
    141             {
    142                 if(checkpoint == person.m_evolution) {
    143                     m_next_id = person.m_id;
    144                     person.m_id = prev_id;
    145                 }
    146             } BOOST_SCOPE_EXIT_END
    147        
    148             // ...
    149        
    150             checkpoint = ++person.m_evolution;
    151         }
    152 
    153 Full code listing can be found in [@../../example/world.cpp world.cpp].
    154 
    155 [endsect]
    156 
    157 [section:alt_relwork Alternatives and Related Work]
    158 
    159 [h3 try-catch]
    160 
    161 This is an example of using a badly designed `File` class.  An
    162 instance of `File` doesn't close a file in a destructor, a programmer
    163 is expected to call the `close` member function explicitly.
    164 
    165         File passwd;
    166         try {
    167             passwd.open("/etc/passwd");
    168             // ...
    169             passwd.close();
    170         }
    171         catch(...) {
    172             log("could not get user info");
    173             if(passwd.is_open())
    174                 passwd.close();
     277        } catch(...) {
     278            std::clog << "could not get user info" << std::endl;
    175279            throw;
    176280        }
    177281
    178 Note the following:
    179 
    180 * the `passwd` object is defined outside of the `try` block because
    181 this object is required inside the `catch` block to close the file,
    182 * the `passwd` object is not fully constructed until after the `open`
    183 member function returns, and
    184 * if opening throws, the `passwd.close()` should not be called,
    185 hence the call to `passwd.is_open()`.
    186 
    187 _scope_exit_ doesn't have any of these problems:
    188 
    189         try {
    190             File passwd("/etc/passwd");
    191             BOOST_SCOPE_EXIT( (&passwd) ) {
    192                 passwd.close();
    193             } BOOST_SCOPE_EXIT_END
    194             // ...
    195         }
    196         catch(...) {
    197             log("could not get user info");
    198             throw;
    199         }
    200 
    201 [h3 RAII]
    202 
    203 _RAII_ is absolutely perfect for the `File` class introduced above.
    204 Use of a properly designed `File` class would look like:
    205 
    206         try {
    207             File passwd("/etc/passwd");
    208             // ...
    209         }
    210         catch(...) {
    211             log("could not get user info");
    212             throw;
    213         }
    214 
    215 However, using _RAII_ to build up a _strong_guarantee_ could introduce
    216 a lot of non-reusable _RAII_ types. For example:
    217 
    218         m_persons.push_back(person);
    219         pop_back_if_not_commit pop_back_if_not_commit_guard(commit, m_persons);
    220 
    221 The `pop_back_if_not_commit` class is either defined out of the scope or
    222 as a local class:
     282However, using __RAII__ to build up a __strong_guarantee__ could introduce a lot of non-reusable __RAII__ types.
     283For example:
     284
     285        persons_.push_back(a_person);
     286        pop_back_if_not_commit pop_back_if_not_commit_guard(commit, persons_);
     287
     288The `pop_back_if_not_commit` class is either defined out of the scope or as a local class:
    223289
    224290        class pop_back_if_not_commit {
    225             bool m_commit;
    226             std::vector<Person>& m_vec;
     291            bool commit_;
     292            std::vector<person>& vec_;
    227293            // ...
    228294            ~pop_back_if_not_commit() {
    229                 if(!m_commit)
    230                     m_vec.pop_back();
     295                if(!commit_) vec_.pop_back();
    231296            }
    232297        };
    233298
    234 In some cases _strong_guarantee_ can be accomplished with standard utilities:
    235 
    236         std::auto_ptr<Person> spSuperMan(new Superman);
    237         m_persons.push_back(spSuperMan.get());
    238         spSuperMan.release(); // m_persons successfully took ownership.
    239 
    240 or with specialized containers such as _ptr_container_ or
    241 _multi_index_.
    242 
    243 [h3 _scope_guard_]
    244 
    245 Imagine that you add a new currency rate:
    246 
    247         bool commit = false;
    248         std::string currency("EUR");
    249         double rate = 1.3326;
    250         std::map<std::string, double> rates;
    251         bool currency_rate_inserted =
    252             rates.insert(std::make_pair(currency, rate)).second;
     299In some cases __strong_guarantee__ can be accomplished with standard utilities:
     300
     301        std::auto_ptr<Person> superman_ptr(new superman());
     302        persons_.push_back(superman_ptr.get());
     303        superman_ptr.release(); // persons_ successfully took ownership
     304
     305Or with specialized containers such as __Boost_PointerContainer__ or __Boost_Multi_Index__.
     306
     307[h5 Scope Guards]
     308
     309Imagine that a new currency rate is introduced before performing a transaction:
     310
     311[scope_guard_decl]
    253312       
    254 and then continue a transaction. If it cannot be completed, you erase
    255 the currency from `rates`. This is how you can do this with _scope_guard_
    256 and _lambda_:
     313If the transaction does not complete, the currency must be erased from `rates`.
     314This can be done with __ScopeGuard__ and __Boost_Lambda__ (or __Boost_Phoenix__):
    257315       
    258         using namespace boost::lambda;
    259        
    260         ON_BLOCK_EXIT(
    261             if_(currency_rate_inserted && !_1) [
    262                 bind(
    263                     static_cast<
    264                         std::map<std::string,double>::size_type (std::map<std::string,double>::*)(std::string const&)
    265                     >(&std::map<std::string,double>::erase)
    266                   , &rates
    267                   , currency
    268                   )
    269             ]
    270           , boost::cref(commit)
    271           );
    272        
    273         // ...
    274        
    275         commit = true;
    276 
    277 Note that
    278 
    279 * Boost.lambda expressions are hard to write correctly, for example,
    280 overloaded function must be explicitly casted, as demonstrated in
    281 this example,
    282 * condition in `if_` expression refers to `commit` variable indirectly
    283 through the `_1` placeholder,
    284 * setting a breakpoint inside `if_[ ... ]` requires in-depth knowledge
    285 of _lambda_ and debugging techniques.
    286 
    287 This code will look much better with native lambda expressions proposed
    288 for C++0x:
    289 
    290         ON_BLOCK_EXIT(
    291             [currency_rate_inserted, &commit, &rates, &currency]() -> void
    292             {
    293                 if(currency_rate_inserted && !commit)
    294                     rates.erase(currency);
    295             }
    296         );
    297 
    298 With _scope_exit_ you can simply do
    299 
    300         BOOST_SCOPE_EXIT( (currency_rate_inserted)(&commit)(&rates)(&currency) )
    301         {
    302             if(currency_rate_inserted && !commit)
    303                 rates.erase(currency);
    304         } BOOST_SCOPE_EXIT_END
    305        
    306         // ...
    307        
    308         commit = true;
    309 
    310 [h3 C++0x]
    311 
    312 In future releases _scope_exit_ will take advantages of C++0x features.
    313 
    314 * Passing capture list as _pp_seq_ will be replaced with a traditional
    315 macro invocation style:
    316 
    317         BOOST_SCOPE_EXIT(currency_rate_inserted, &commit, &rates, &currency)
    318         {
    319             if(currency_rate_inserted && !commit)
    320                 rates.erase(currency);
    321         } BOOST_SCOPE_EXIT_END
    322        
    323 * `BOOST_SCOPE_EXIT_END` will be replaced with a semicolon:
    324 
    325         BOOST_SCOPE_EXIT(currency_rate_inserted, &commit, &rates, &currency)
    326         {
    327             if(currency_rate_inserted && !commit)
    328                 rates.erase(currency);
    329         };
    330 
    331 * Users will be able to capture local variables implicitly with lambda
    332 capture defaults `&` and `=`:
    333 
    334         BOOST_SCOPE_EXIT(&, currency_rate_inserted)
    335         {
    336             if(currency_rate_inserted && !commit)
    337                 rates.erase(currency);
    338         };
    339 
    340 * It will be possible to capture `this` pointer.
    341 
    342 [h3 The D Programming Language]
    343 
    344 _ScopeExit_ is similar to _D_scope_exit_ feature built
    345 into the _D_ programming language.
    346 
    347 A curious reader may notice that the library doesn't implement
    348 `scope(success)` and `scope(failure)` of the _D_ language.
    349 Unfortunately, it's not possible in C++ because failure or success
    350 condition cannot be determined by calling `std::uncaught_exception`.
    351 It's not a big problem, though. These two constructs can be
    352 expressed in terms of _D_scope_exit_ and a `bool commit` variable
    353 as explained in _Tutorial_. Refer to
    354 [@http://www.gotw.ca/gotw/047.htm Guru of the Week #47]
    355 for more details about `std::uncaught_exception` and if it has
    356 any good use at all.
    357 
    358 [endsect]
    359 
    360 [section:compilers Supported Compilers]
    361 
    362 The library should be usable on any compiler that supports _typeof_
    363 except
    364 
    365 * MSVC 7.1 and 8.0 fail to link if a function with _scope_exit_
    366 is included by multiple translation units.
    367 * GCC 3.3 can't compile _scope_exit_ inside a template. See
    368 [@http://lists.boost.org/Archives/boost/2007/02/116235.php this thread]
    369 for more details.
    370 
    371 The author tested the library on GCC 3.3, 3.4, 4.1, 4.2 and Intel 10.1.
    372 
    373 [endsect]
    374 
    375 [section:conf Configuration]
    376 
    377 Normally, no configuration is required for the library but
    378 note that the library depends on _typeof_ and you may want
    379 to configure or enforce _typeof_emulation_.
    380 
    381 [endsect]
    382 
    383 [section:ref Reference]
    384 
    385 [h3 BOOST_SCOPE_EXIT]
    386 
    387 A _scope_exit_ declaration has the following synopsis:
    388 
    389         #include <boost/scope_exit.hpp>
    390 
    391         BOOST_SCOPE_EXIT ( scope-exit-capture-list )
    392             function-body
    393         BOOST_SCOPE_EXIT_END
    394 
    395 where
    396 
    397         scope-exit-capture-list:
    398             ( scope-exit-capture )
    399             scope-exit-capture-list ( scope-exit-capture )
    400        
    401         scope-exit-capture:
    402             identifier
    403             &identifier
    404        
    405 The _scope_exit_ declaration schedules an execution of `scope-exit-body`
    406 at the end of the current scope. The `scope-exit-body` statements are
    407 executed in the reverse order of _scope_exit_ declarations in the given
    408 scope. The scope must be local.
    409 
    410 Each `identifier` in `scope-exit-capture-list` must be a valid name
    411 in enclosing scope and it must appear exactly once in the list.
    412 If a `scope-exit-capture` starts with the ampersand sign `&`, the
    413 corresponding `identifier` will be available inside `scope-exit-body`;
    414 otherwise, a copy of it will be made at the point of _scope_exit_
    415 declaration and that copy will be available inside `scope-exit-body`.
    416 In the latter case, the `idenitifer` must be `CopyConstructible`.
    417 
    418 Only identifiers listed in `scope-exit-capture-list`, static variables,
    419 `extern` variables and functions, and enumerations from the enclosing
    420 scope can be used inside the `scope-exit-body`.
    421 
    422 [note `this` pointer is not an identifier and cannot be passed to
    423 ` scope-exit-capture-list`.]
    424 
    425 The _scope_exit_ uses _typeof_ to determine types of
    426 `scope-exit-capture-list` elements. In order to compile code in
    427 _typeof_emulation_ mode, all types should be registered with
    428 _typeof_REGISTER_TYPE_ or _typeof_REGISTER_TEMPLATE_ macros,
    429 or appropriate _typeof_ headers should be included.
    430 
    431 [h3 BOOST_SCOPE_EXIT_TPL]
    432 
    433 This macro is a workaround for various versions of gcc. These compilers
    434 don't compile _scope_exit_ declaration inside function templates. As a
    435 workaround, the `_TPL` suffix should be appended to `BOOST_SCOPE_EXIT`.
    436 
    437 The problem boils down to the following code:
    438 
    439         template<class T> void foo(T const& t) {
    440             int i = 0;
    441             struct Local {
    442                 typedef __typeof__(i) typeof_i;
    443                 typedef __typeof__(t) typeof_t;
    444             };
    445             typedef Local::typeof_i i_type;
    446             typedef Local::typeof_t t_type;
    447         }
    448        
    449         int main() { foo(0); }
    450 
    451 This can be fixed by adding `typename` in front of `Local::typeof_i` and
    452 `Local::typeof_t`.
    453 
    454 See also [@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37920 GCC bug 37920].
    455 
    456 [note Although `BOOST_SCOPE_EXIT_TPL` has the same suffix as the
    457 `BOOST_TYPEOF_TPL`, it doesn't follow a convention of the _typeof_.]
    458 
    459 [endsect]
    460 
    461 [section:acknowledge Acknowledge]
    462 
    463 (in chronological order)
    464 
    465 Maxim Yegorushkin for sending me a code where he used a local struct
    466 to clean up resources.
    467 
    468 Andrei Alexandrescu for pointing me to _D_scope_exit_ construct of
    469 the _D_ programming language.
    470 
    471 Pavel Vozenilek and Maxim Yanchenko for reviews of early drafts of
    472 the library.
     316    using namespace boost::lambda;
     317
     318    ON_BLOCK_EXIT(
     319        if_(currency_rate_inserted && !_1) [
     320            bind(
     321                static_cast<
     322                    std::map<std::string, double>::size_type
     323                    (std::map<std::string, double>::*)(std::string const&)
     324                >(&std::map<std::string, double>::erase)
     325              , &rates
     326              , currency
     327            )
     328        ]
     329      , boost::cref(commit)
     330      );
     331
     332    // ...
     333
     334    commit = true;
     335
     336Note the following issues with this approach:
     337
     338* __Boost_Lambda__ expressions are hard to write correctly (e.g., overloaded functions must be explicitly casted, as demonstrated in the example above).
     339* The condition in the `if_` expression refers to `commit` variable indirectly through the `_1` placeholder reducing readability.
     340* Setting a breakpoint inside `if_[...]` requires in-depth knowledge of __Boost_Lambda__ and debugging techniques.
     341
     342This code will look much better with C++11 lambdas:
     343
     344    ON_BLOCK_EXIT(
     345        [currency_rate_inserted, &commit, &rates, &currency]() {
     346            if(currency_rate_inserted && !commit) rates.erase(currency);
     347        }
     348    );
     349   
     350    // ...
     351   
     352    commit = true;
     353
     354With __Boost_ScopeExit__ we can simply do the following (see also [@../../example/scope_guard.cpp =scope_guard.cpp=]):
     355
     356[scope_guard_exit]
     357
     358[h5 The D Programming Language]
     359
     360__Boost_ScopeExit__ is similar to __D_scope_exit__ feature built into the __D__ programming language.
     361
     362A curious reader may notice that the library does not implement `scope(success)` and `scope(failure)` of the __D__ language.
     363Unfortunately, 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 more details about `std::uncaught_exception` and if it has any good use at all).
     364However, 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 as explained in the __Tutorial__ section.
     365
     366[h5 C++11 Lambdas]
     367
     368Using C++11 lambdas, it is relatively easy to implement the __Boost_ScopeExit__ construct.
     369For example (see also [@../../test/world_lambda.cpp =world_lambda.cpp=]):
     370
     371[world_lambda]
     372
     373However, this library allows to program the __Boost_ScopeExit__ construct in a way that is portable between C++03 and C++11 compilers.
     374
     375[endsect]
     376
     377[section:No_Variadic_Macros Annex: No Variadic Macros]
     378
     379This section presents an alternative syntax for compilers without variadic macro support.
     380
     381[h5 Sequence Syntax]
     382
     383Most modern compilers support variadic macros (notably, these include GCC, MSVC, and all C++11 compilers).
     384However, 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 `()`:
     385
     386    (capture1) (capture2) ... // All compilers.
     387
     388Instead of the comma-separated list that we have seen so far which requires variadic macros:
     389
     390    capture1, capture2, ... // Only compilers with variadic macros.
     391
     392For example, the following syntax is accepted on all compilers with and without variadic macros (see also [@../../test/world_seq.cpp =world_seq.cpp=]):
     393
     394[world_seq]
     395
     396Furthermore, older versions of this library used to only support the __Boost_Preprocessor__ sequence syntax so the above syntax is also supported for backward compatibility.
     397However, in the current version of this library and on compilers with variadic macros, the comma-separated syntax we have seen so far is preferred because more readable (see also [@../../test/world.cpp =world.cpp=]):
     398
     399[world]
     400
     401Note how the same macros accept both syntaxes on compilers with variadic macros and only the __Boost_Preprocessor__ sequence syntax on compilers without variadic macros.
     402Finally, 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=]):
     403
     404[world_void]
     405
     406[h5 Examples]
     407
     408The following is a list of most of the examples presented in this documentation reprogrammed using the __Boost_Preprocessor__ sequence syntax instead of the comma-separated list:
     409
     410[table
     411    [ [Files] ]
     412    [ [[@../../test/world_checkpoint_seq.cpp =world_checkpoint_seq.cpp=]] ]
     413    [ [[@../../test/world_this_seq.cpp =world_this_seq.cpp=]] ]
     414    [ [[@../../test/world_checkpoint_all_seq.cpp =world_checkpoint_all_seq.cpp=]] ]
     415    [ [[@../../test/world_tpl_seq.cpp =world_tpl_seq.cpp=]] ]
     416    [ [[@../../example/try_catch_seq.cpp =try_catch_seq.cpp=]] ]
     417    [ [[@../../example/scope_guard_seq.cpp =scope_guard_seq.cpp=]] ]
     418]
     419
     420[endsect]
     421
     422[section:Acknowledgements Acknowledgements]
     423
     424Alexander Nasonov is the original library author.
     425
     426Lorenzo Caminiti added variadic macro support, capture of the object `this_`, empty captures using `void`, and `BOOST_SCOPE_EXIT_ALL`.
     427
     428/Thanks to the following people (in chronological order)./
     429
     430Maxim Yegorushkin for sharing code where he used a local struct to clean up resources.
     431
     432Andrei Alexandrescu for pointing out the __D_scope_exit__ construct of the __D__ programming language.
     433
     434Pavel Vozenilek and Maxim Yanchenko for reviews of early drafts of the library.
    473435
    474436Steven Watanabe for his valuable ideas.
     
    478440Richard Webb for testing the library on MSVC compiler.
    479441
    480 [endsect]
     442Adam Butcher for a workaround to error C2355 when deducing the type of `this` on some MSVC versions.
     443
     444[endsect]
     445
  • trunk/libs/scope_exit/index.html

    r50847 r77030  
    1 
    2 <!--
    3 Copyright 2009 Alexander Nasonov.
    4 Distributed under the Boost Software License, Version 1.0. (See accompanying
    5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
    6 -->
    7 
     1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    82<html>
    9 <head>
     3  <head>
    104    <meta http-equiv="refresh" content="0; URL=doc/html/index.html">
    11 </head>
    12 <body>
    13 Automatic redirection failed, please go to
    14 <a href="doc/html/index.html">doc/html/index.html</a>
    15 </body>
     5  </head>
     6  <body>
     7    Automatic redirection failed, click this
     8    <a href="doc/html/index.html">link</a> &nbsp;<hr>
     9    <p>© Copyright Alexander Nasonov, Lorenzo Caminiti, 2006-2012</p>
     10    <p>Distributed under the Boost Software License, Version 1.0 (see
     11    accompanying file <a href="../../LICENSE_1_0.txt">
     12    LICENSE_1_0.txt</a> or a copy at
     13    <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
     14  </body>
    1615</html>
  • trunk/libs/scope_exit/test/Jamfile.v2

    r50620 r77030  
    1 # Copyright Alexander Nasonov 2007
    2 #
    3 # Distributed under the Boost Software License, Version 1.0.
    4 # (See accompanying file LICENSE_1_0.txt or copy at
     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
    56# http://www.boost.org/LICENSE_1_0.txt)
    6 
    7 # TODO: get rid of dummy .cpp files that only #include other .cpp file.
     7# Home at http://www.boost.org/libs/scope_exit
    88
    99import testing ;
    1010
    11 run native.cpp    ../../../libs/test/build//boost_test_exec_monitor :  :  : <define>BOOST_TYPEOF_NATIVE          :  ;
    12 run emulation.cpp ../../../libs/test/build//boost_test_exec_monitor :  :  : <define>BOOST_TYPEOF_EMULATION       :  ;
     11project
     12    :   requirements
     13        <library>/boost/test//boost_test_exec_monitor
     14        <library>/boost//unit_test_framework
     15        <link>static
     16    ;
    1317
    14 run native_tpl.cpp    ../../../libs/test/build//boost_test_exec_monitor :  :  : <define>BOOST_TYPEOF_NATIVE     :  ;
    15 run emulation_tpl.cpp ../../../libs/test/build//boost_test_exec_monitor :  :  : <define>BOOST_TYPEOF_EMULATION  :  ;
     18test-suite world_tests
     19    :   [ run world.cpp ]
     20        [ run world_seq.cpp ]
     21       
     22        [ run world_void.cpp ]
     23       
     24        [ run world_this.cpp ]
     25        [ run world_this_seq.cpp ]
     26       
     27        [ run world_tpl.cpp ]
     28        [ run world_tpl_seq.cpp ]
     29       
     30        [ run world_checkpoint.cpp ]
     31        [ run world_checkpoint_seq.cpp ]
     32       
     33        [ run world_checkpoint_all.cpp ]
     34        [ run world_checkpoint_all_seq.cpp ]
     35       
     36        [ run world_lambda.cpp ]
     37    ;
    1638
    17 compile-fail native_const_error.cpp    : <define>BOOST_TYPEOF_NATIVE    ;
    18 compile-fail emulation_const_error.cpp : <define>BOOST_TYPEOF_EMULATION ;
     39test-suite native_tests
     40    :   [ run native.cpp : : : <define>BOOST_TYPEOF_NATIVE ]
     41        [ run native_tpl.cpp : : : <define>BOOST_TYPEOF_NATIVE ]
     42        [ run native_this.cpp : : : <define>BOOST_TYPEOF_NATIVE ]
     43        [ compile-fail native_const_error.cpp : <define>BOOST_TYPEOF_NATIVE ]
     44        [ compile-fail native_cv_error.cpp : <define>BOOST_TYPEOF_NATIVE ]
     45        # Following test is known to fail on MSVC 7.1 and 8.0.
     46        [ run native_tu_test.cpp native_tu1.cpp native_tu2.cpp : : :
     47                <define>BOOST_TYPEOF_NATIVE ]
     48    ;
    1949
    20 compile-fail native_cv_error.cpp    : <define>BOOST_TYPEOF_NATIVE    ;
    21 compile-fail emulation_cv_error.cpp : <define>BOOST_TYPEOF_EMULATION ;
     50test-suite emulation_tests
     51    :   [ run native.cpp : : : <define>BOOST_TYPEOF_EMULATION : emulation : ]
     52        [ run native_tpl.cpp : : : <define>BOOST_TYPEOF_EMULATION :
     53                emulation_tpl : ]
     54        [ run native_this.cpp : : : <define>BOOST_TYPEOF_EMULATION :
     55                emulation_this : ]
     56        [ compile-fail native_const_error.cpp : <define>BOOST_TYPEOF_EMULATION :
     57                emulation_const_error : ]
     58        [ compile-fail native_cv_error.cpp : <define>BOOST_TYPEOF_EMULATION :
     59                emulation_cv_error : ]
     60        # Following test is known to fail on MSVC 7.1 and 8.0.
     61        [ run native_tu_test.cpp native_tu1.cpp native_tu2.cpp : : :
     62                <define>BOOST_TYPEOF_EMULATION : emulation_tu_test : ]
     63    ;
    2264
    23 run native_tu_test.cpp    native_tu1.cpp native_tu2.cpp ../../../libs/test/build//boost_test_exec_monitor  :  :  : <define>BOOST_TYPEOF_NATIVE    :  ;
    24 run emulation_tu_test.cpp native_tu1.cpp native_tu2.cpp ../../../libs/test/build//boost_test_exec_monitor  :  :  : <define>BOOST_TYPEOF_EMULATION :  ;
    25 
  • trunk/libs/scope_exit/test/native.cpp

    r75550 r77030  
    1 // Copyright Alexander Nasonov 2007-2008, 2011
    2 //
    3 // Distributed under the Boost Software License, Version 1.0.
    4 // (See accompanying file LICENSE_1_0.txt or copy at
     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
    56// http://www.boost.org/LICENSE_1_0.txt)
     7// Home at http://www.boost.org/libs/scope_exit
    68
     9#include <boost/scope_exit.hpp>
     10#include <boost/typeof/typeof.hpp>
     11#include <boost/typeof/std/string.hpp>
     12#include <boost/test/unit_test.hpp>
    713#include <iostream>
    814#include <ostream>
    915#include <string>
    10 
    11 #include <boost/scope_exit.hpp>
    12 
    13 #include <boost/typeof/typeof.hpp>
    14 #include <boost/typeof/std/string.hpp>
    15 #include <boost/test/unit_test.hpp>
    1616
    1717using namespace boost::unit_test;
     
    2020
    2121template<int Dummy = 0>
    22 struct Holder
    23 {
     22struct Holder {
    2423    static long g_long;
    2524};
     
    2726template<int Dummy> long Holder<Dummy>::g_long;
    2827
    29 void test_non_local()
    30 {
     28void test_non_local(void) {
    3129    // ... and one local variable as well:
    3230    int i = 0;
    3331
    34     BOOST_SCOPE_EXIT( (i) )
    35     {
    36         BOOST_CHECK(i == 0);
    37         BOOST_CHECK(Holder<>::g_long == 3);
    38         BOOST_CHECK(g_str == "try: g_str");
     32    BOOST_SCOPE_EXIT(void) {
     33        BOOST_CHECK( Holder<>::g_long == 3 );
    3934    } BOOST_SCOPE_EXIT_END
    4035
    41     BOOST_SCOPE_EXIT( (&i) )
    42     {
    43         BOOST_CHECK(i == 3);
    44         BOOST_CHECK(Holder<>::g_long == 3);
    45         BOOST_CHECK(g_str == "try: g_str");
     36    BOOST_SCOPE_EXIT(i) {
     37        BOOST_CHECK( i == 0 );
     38        BOOST_CHECK( Holder<>::g_long == 3 );
     39        BOOST_CHECK( g_str == "try: g_str" );
     40    } BOOST_SCOPE_EXIT_END
     41
     42    BOOST_SCOPE_EXIT(&i) {
     43        BOOST_CHECK( i == 3 );
     44        BOOST_CHECK( Holder<>::g_long == 3 );
     45        BOOST_CHECK( g_str == "try: g_str" );
    4646    } BOOST_SCOPE_EXIT_END
    4747
     
    5050        Holder<>::g_long = 1;
    5151
    52         BOOST_SCOPE_EXIT( (&i) )
    53         {
     52        BOOST_SCOPE_EXIT(&i) {
    5453            i = 1;
    5554            g_str = "g_str";
    5655        } BOOST_SCOPE_EXIT_END
    5756
    58         BOOST_SCOPE_EXIT( (&i) )
    59         {
    60           try
    61           {
    62               i = 2;
    63               Holder<>::g_long = 2;
    64               throw 0;
    65           } catch(...) {}
     57        BOOST_SCOPE_EXIT(&i) {
     58            try {
     59                i = 2;
     60                Holder<>::g_long = 2;
     61                throw 0;
     62            } catch(...) {}
    6663        } BOOST_SCOPE_EXIT_END
    6764
    68         BOOST_CHECK(i == 0);
    69         BOOST_CHECK(g_str == "");
    70         BOOST_CHECK(Holder<>::g_long == 1);
     65        BOOST_CHECK( i == 0 );
     66        BOOST_CHECK( g_str == "" );
     67        BOOST_CHECK( Holder<>::g_long == 1 );
    7168    }
    7269
    73     BOOST_CHECK(Holder<>::g_long == 2);
    74     BOOST_CHECK(g_str == "g_str");
    75     BOOST_CHECK(i == 1); // Check that first declared is executed last
     70    BOOST_CHECK( Holder<>::g_long == 2 );
     71    BOOST_CHECK( g_str == "g_str" );
     72    BOOST_CHECK( i == 1 ); // Check that first declared is executed last.
    7673
    77     BOOST_SCOPE_EXIT( (&i) )
    78     {
    79         BOOST_CHECK(i == 3);
    80         BOOST_CHECK(Holder<>::g_long == 3);
    81         BOOST_CHECK(g_str == "try: g_str");
     74    BOOST_SCOPE_EXIT(&i) {
     75        BOOST_CHECK( i == 3 );
     76        BOOST_CHECK( Holder<>::g_long == 3 );
     77        BOOST_CHECK( g_str == "try: g_str" );
    8278    } BOOST_SCOPE_EXIT_END
    8379
    84     BOOST_SCOPE_EXIT( (i) )
    85     {
    86         BOOST_CHECK(i == 1);
    87         BOOST_CHECK(Holder<>::g_long == 3);
    88         BOOST_CHECK(g_str == "try: g_str");
     80    BOOST_SCOPE_EXIT(i) {
     81        BOOST_CHECK( i == 1 );
     82        BOOST_CHECK( Holder<>::g_long == 3 );
     83        BOOST_CHECK( g_str == "try: g_str" );
    8984    } BOOST_SCOPE_EXIT_END
    9085
    91     try
    92     {
    93         BOOST_SCOPE_EXIT( (&i) )
    94         {
     86    try {
     87        BOOST_SCOPE_EXIT(&i) {
    9588            i = 3;
    9689            g_str = "try: g_str";
    9790        } BOOST_SCOPE_EXIT_END
    9891       
    99         BOOST_SCOPE_EXIT( (&i) )
    100         {
     92        BOOST_SCOPE_EXIT(&i) {
    10193            i = 4;
    10294            Holder<>::g_long = 3;
    10395        } BOOST_SCOPE_EXIT_END
    10496
    105         BOOST_CHECK(i == 1);
    106         BOOST_CHECK(g_str == "g_str");
    107         BOOST_CHECK(Holder<>::g_long == 2);
     97        BOOST_CHECK( i == 1 );
     98        BOOST_CHECK( g_str == "g_str" );
     99        BOOST_CHECK( Holder<>::g_long == 2 );
    108100
    109101        throw 0;
    110     }
    111     catch(int)
    112     {
    113         BOOST_CHECK(Holder<>::g_long == 3);
    114         BOOST_CHECK(g_str == "try: g_str");
    115         BOOST_CHECK(i == 3); // Check that first declared is executed last
     102    } catch(int) {
     103        BOOST_CHECK( Holder<>::g_long == 3 );
     104        BOOST_CHECK( g_str == "try: g_str" );
     105        BOOST_CHECK( i == 3 ); // Check that first declared is executed last.
    116106    }
    117107}
    118108
    119 bool foo()
    120 {
    121     return true;
    122 }
     109bool foo(void) { return true; }
    123110
    124 bool foo2()
    125 {
    126     return false;
    127 }
     111bool foo2(void) { return false; }
    128112
    129 void test_types()
    130 {
    131     bool (*pf)() = 0;
    132     bool (&rf)() = foo;
     113void test_types(void) {
     114    bool (*pf)(void) = 0;
     115    bool (&rf)(void) = foo;
    133116    bool results[2] = {};
    134117
    135118    {
    136         BOOST_SCOPE_EXIT( (&results)(&pf)(&rf) )
    137         {
     119        BOOST_SCOPE_EXIT(&results, &pf, &rf) {
    138120            results[0] = pf();
    139121            results[1] = rf();
     
    143125        pf = &foo;
    144126
    145         BOOST_CHECK(results[0] == false);
    146         BOOST_CHECK(results[1] == false);
     127        BOOST_CHECK( results[0] == false );
     128        BOOST_CHECK( results[1] == false );
    147129    }
    148130
    149     BOOST_CHECK(results[0] == true);
    150     BOOST_CHECK(results[1] == true);
     131    BOOST_CHECK( results[0] == true );
     132    BOOST_CHECK( results[1] == true );
    151133
    152134    {
    153         BOOST_SCOPE_EXIT( (&results)(pf) )
    154         {
     135        BOOST_SCOPE_EXIT(&results, pf) {
    155136            results[0] = !pf();
    156137            results[1] = !pf();
     
    161142        pf = 0;
    162143
    163         BOOST_CHECK(results[0] == true);
    164         BOOST_CHECK(results[1] == true);
     144        BOOST_CHECK( results[0] == true );
     145        BOOST_CHECK( results[1] == true );
    165146    }
    166147
    167     BOOST_CHECK(pf == 0);
    168     BOOST_CHECK(results[0] == false);
    169     BOOST_CHECK(results[1] == false);
     148    BOOST_CHECK( pf == 0 );
     149    BOOST_CHECK( results[0] == false );
     150    BOOST_CHECK( results[1] == false );
    170151}
    171152
    172 void test_cxx0x()
    173 {
    174 #if defined(BOOST_SCOPE_EXIT_AUX_CXX0X)
     153void test_cpp11(void) {
     154#if !defined(BOOST_NO_LAMBDAS) && !defined(BOOST_SCOPE_EXIT_CONFIG_NO_CPP11)
    175155    int i = 0, j = 1;
    176156
    177157    {
    178         BOOST_SCOPE_EXIT((=))
    179         {
     158        BOOST_SCOPE_EXIT_ALL(=) {
    180159            i = j = 1; // modify copies
    181160        };
    182161    }
    183     BOOST_CHECK(i == 0);
    184     BOOST_CHECK(j == 1);
     162    BOOST_CHECK( i == 0 );
     163    BOOST_CHECK( j == 1 );
    185164
    186165    {
    187         BOOST_SCOPE_EXIT((&))
    188         {
     166        BOOST_SCOPE_EXIT_ALL(&) {
    189167            i = 1;
    190168            j = 2;
    191169        };
    192         BOOST_CHECK(i == 0);
    193         BOOST_CHECK(j == 1);
     170        BOOST_CHECK( i == 0 );
     171        BOOST_CHECK( j == 1 );
    194172    }
    195     BOOST_CHECK(i == 1);
    196     BOOST_CHECK(j == 2);
     173    BOOST_CHECK( i == 1 );
     174    BOOST_CHECK( j == 2 );
    197175
    198176    {
    199         BOOST_SCOPE_EXIT((=)(&j))
    200         {
     177        BOOST_SCOPE_EXIT_ALL(=, &j) {
    201178            i = 2; // modify a copy
    202179            j = 3;
    203180        };
    204         BOOST_CHECK(i == 1);
    205         BOOST_CHECK(j == 2);
     181        BOOST_CHECK( i == 1 );
     182        BOOST_CHECK( j == 2 );
    206183    }
    207     BOOST_CHECK(i == 1);
    208     BOOST_CHECK(j == 3);
    209 
     184    BOOST_CHECK( i == 1 );
     185    BOOST_CHECK( j == 3 );
    210186#endif
    211187}
    212188
    213 test_suite* init_unit_test_suite( int, char* [] )
    214 {
     189test_suite* init_unit_test_suite(int, char* []) {
    215190    framework::master_test_suite().p_name.value = "Unit test for ScopeExit";
    216     framework::master_test_suite().add( BOOST_TEST_CASE( &test_non_local ));
    217     framework::master_test_suite().add( BOOST_TEST_CASE( &test_types     ));
    218     framework::master_test_suite().add( BOOST_TEST_CASE( &test_cxx0x     ));
     191    framework::master_test_suite().add(BOOST_TEST_CASE(&test_non_local));
     192    framework::master_test_suite().add(BOOST_TEST_CASE(&test_types));
     193    framework::master_test_suite().add(BOOST_TEST_CASE(&test_cpp11));
    219194    return 0;
    220195}
     196
  • trunk/libs/scope_exit/test/native_const_error.cpp

    r50620 r77030  
    1 // Copyright Alexander Nasonov 2007-2008
    2 //
    3 // Distributed under the Boost Software License, Version 1.0.
    4 // (See accompanying file LICENSE_1_0.txt or copy at
     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
    56// http://www.boost.org/LICENSE_1_0.txt)
     7// Home at http://www.boost.org/libs/scope_exit
    68
    79#include <boost/scope_exit.hpp>
    810
    9 int main()
    10 {
     11int main(void) {
    1112    int const i = 0;
    12     BOOST_SCOPE_EXIT( (&i) )
    13     {
     13    BOOST_SCOPE_EXIT(&i) {
    1414        i = 5;
    1515    } BOOST_SCOPE_EXIT_END
  • trunk/libs/scope_exit/test/native_cv_error.cpp

    r50620 r77030  
    1 // Copyright Alexander Nasonov 2007-2008
    2 //
    3 // Distributed under the Boost Software License, Version 1.0.
    4 // (See accompanying file LICENSE_1_0.txt or copy at
     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
    56// http://www.boost.org/LICENSE_1_0.txt)
     7// Home at http://www.boost.org/libs/scope_exit
    68
     9#include <boost/scope_exit.hpp>
     10#include <boost/typeof/typeof.hpp>
     11#include <boost/typeof/std/string.hpp>
    712#include <string>
    813
    9 #include <boost/scope_exit.hpp>
    10 
    11 #include <boost/typeof/typeof.hpp>
    12 #include <boost/typeof/std/string.hpp>
    13 
    14 int main()
    15 {
     14int main(void) {
    1615    std::string const volatile s;
    17     BOOST_SCOPE_EXIT( (&s) )
    18     {
     16    BOOST_SCOPE_EXIT(&s) {
    1917        s = "";
    2018    } BOOST_SCOPE_EXIT_END
  • trunk/libs/scope_exit/test/native_tpl.cpp

    r50620 r77030  
    1 // Copyright Alexander Nasonov 2007-2008
    2 //
    3 // Distributed under the Boost Software License, Version 1.0.
    4 // (See accompanying file LICENSE_1_0.txt or copy at
     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
    56// http://www.boost.org/LICENSE_1_0.txt)
     7// Home at http://www.boost.org/libs/scope_exit
    68
     9#include <boost/scope_exit.hpp>
     10#include <boost/rational.hpp>
     11#include <boost/typeof/typeof.hpp>
     12#include <boost/typeof/std/vector.hpp>
     13#include <boost/test/unit_test.hpp>
    714#include <iostream>
    815#include <ostream>
    916#include <vector>
    1017
    11 #include <boost/scope_exit.hpp>
    12 
    13 #include <boost/rational.hpp>
    14 #include <boost/typeof/typeof.hpp>
    15 #include <boost/typeof/std/vector.hpp>
    16 #include <boost/test/unit_test.hpp>
    17 
    1818using namespace boost::unit_test;
    1919
    2020template<class type>
    21 void tpl_long( type tval
    22              , type& t
    23              , type const& tc
    24              , type volatile& tv
    25              , type const volatile& tcv
    26              )
    27 {
     21void tpl_long(
     22      type tval
     23    , type & t
     24    , type const& tc
     25    , type volatile& tv
     26    , type const volatile& tcv
     27) {
    2828    int i = 0; // non-dependent name
    2929    type const remember(tval);
    3030
    3131    {
    32         BOOST_SCOPE_EXIT_TPL( (&tval)(&t)(&tc)(&tv)(&tcv)(&i) )
    33         {
     32        BOOST_SCOPE_EXIT_TPL(&tval, &t, &tc, &tv, &tcv, &i) {
    3433            tval = 1;
    3534            ++t;
    3635            ++tv;
    37         }
    38         BOOST_SCOPE_EXIT_END
     36        } BOOST_SCOPE_EXIT_END
    3937
    40         BOOST_CHECK(t == remember);
    41         BOOST_CHECK(tval == remember);
     38        BOOST_CHECK( t == remember );
     39        BOOST_CHECK( tval == remember );
    4240    }
    4341
    44     BOOST_CHECK(tval == 1);
    45     BOOST_CHECK(t == remember + 2);
     42    BOOST_CHECK( tval == 1 );
     43    BOOST_CHECK( t == remember + 2 );
    4644}
    4745
    4846template<class Vector, int Value>
    49 void tpl_vector( Vector vval
    50                , Vector& v
    51                , Vector const& vc
    52                )
    53 {
     47void tpl_vector(
     48      Vector vval
     49    , Vector & v
     50    , Vector const& vc
     51) {
    5452    Vector const remember(vval);
    5553
    5654    {
    57         BOOST_SCOPE_EXIT_TPL( (&vval)(&v)(&vc) )
    58         {
     55        BOOST_SCOPE_EXIT_TPL(&vval, &v, &vc) {
    5956            v.push_back(-Value);
    6057            vval.push_back(Value);
    61         }
    62         BOOST_SCOPE_EXIT_END
     58        } BOOST_SCOPE_EXIT_END
    6359
    64         BOOST_CHECK(v.size() == remember.size());
    65         BOOST_CHECK(vval.size() == remember.size());
     60        BOOST_CHECK( v.size() == remember.size() );
     61        BOOST_CHECK( vval.size() == remember.size() );
    6662    }
    6763
    68     BOOST_CHECK(v.size() == 1 + remember.size());
    69     BOOST_CHECK(vval.size() == 1 + remember.size());
     64    BOOST_CHECK( v.size() == 1 + remember.size() );
     65    BOOST_CHECK( vval.size() == 1 + remember.size() );
    7066}
    7167
    72 void test_tpl()
    73 {
     68void test_tpl(void) {
    7469    long l = 137;
    7570    tpl_long(l, l, l, l, l);
     
    7974}
    8075
    81 test_suite* init_unit_test_suite( int, char* [] )
    82 {
     76test_suite* init_unit_test_suite(int, char* []) {
    8377    framework::master_test_suite().p_name.value = "Unit test for ScopeExit TPL";
    84     framework::master_test_suite().add( BOOST_TEST_CASE( &test_tpl ));
     78    framework::master_test_suite().add(BOOST_TEST_CASE(&test_tpl));
    8579    return 0;
    8680}
  • trunk/libs/scope_exit/test/native_tu1.cpp

    r50620 r77030  
    1 // Copyright Alexander Nasonov 2007-2008
    2 //
    3 // Distributed under the Boost Software License, Version 1.0.
    4 // (See accompanying file LICENSE_1_0.txt or copy at
     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
    56// http://www.boost.org/LICENSE_1_0.txt)
     7// Home at http://www.boost.org/libs/scope_exit
    68
    79#include "tu_test.hpp"
    810
    9 int tu1()
    10 {
     11int tu1(void) {
    1112    return inline_f() + template_f(1);
    1213}
  • trunk/libs/scope_exit/test/native_tu2.cpp

    r50620 r77030  
    1 // Copyright Alexander Nasonov 2007-2008
    2 //
    3 // Distributed under the Boost Software License, Version 1.0.
    4 // (See accompanying file LICENSE_1_0.txt or copy at
     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
    56// http://www.boost.org/LICENSE_1_0.txt)
     7// Home at http://www.boost.org/libs/scope_exit
    68
    79#include "tu_test.hpp"
    810
    9 int tu2()
    10 {
     11int tu2(void) {
    1112    return inline_f() + template_f(2);
    1213}
  • trunk/libs/scope_exit/test/native_tu_test.cpp

    r50620 r77030  
    1 // Copyright Alexander Nasonov 2007-2008
    2 //
    3 // Distributed under the Boost Software License, Version 1.0.
    4 // (See accompanying file LICENSE_1_0.txt or copy at
     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
    56// http://www.boost.org/LICENSE_1_0.txt)
     7// Home at http://www.boost.org/libs/scope_exit
    68
    79#include "tu_test.hpp"
    8 
    910#include <boost/test/unit_test.hpp>
    1011
    1112using namespace boost::unit_test;
    1213
    13 void test()
    14 {
    15     BOOST_CHECK(tu1() == 1);
    16     BOOST_CHECK(tu2() == 2);
     14void test(void) {
     15    BOOST_CHECK( tu1() == 1 );
     16    BOOST_CHECK( tu2() == 2 );
    1717}
    1818
    19 test_suite* init_unit_test_suite( int, char* [] )
    20 {
     19test_suite* init_unit_test_suite(int, char* []) {
    2120    framework::master_test_suite().p_name.value = "TU unit test for ScopeExit";
    22     framework::master_test_suite().add( BOOST_TEST_CASE( &test ));
     21    framework::master_test_suite().add(BOOST_TEST_CASE(&test));
    2322    return 0;
    2423}
     24
  • trunk/libs/scope_exit/test/tu_test.hpp

    r75550 r77030  
    1 // Copyright Alexander Nasonov 2007-2008
    2 //
    3 // Distributed under the Boost Software License, Version 1.0.
    4 // (See accompanying file LICENSE_1_0.txt or copy at
     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
    56// http://www.boost.org/LICENSE_1_0.txt)
     7// Home at http://www.boost.org/libs/scope_exit
    68
    79#include <boost/scope_exit.hpp>
    810
    9 int tu1();
    10 int tu2();
     11int tu1(void);
     12int tu2(void);
    1113
    12 inline int inline_f()
    13 {
     14inline int inline_f(void) {
    1415    int i = 99;
    1516    {
    16         BOOST_SCOPE_EXIT( (&i) ) { i = -1; } BOOST_SCOPE_EXIT_END
     17        BOOST_SCOPE_EXIT(&i) { i = -1; } BOOST_SCOPE_EXIT_END
    1718    }
    1819    return i;
     
    2122#if !defined(BOOST_SCOPE_EXIT_AUX_GCC) || BOOST_SCOPE_EXIT_AUX_GCC >= 304
    2223template<class Int>
    23 Int template_f(Int i)
    24 {
     24Int template_f(Int i) {
    2525    {
    26         BOOST_SCOPE_EXIT_TPL( (&i) ) { ++i; } BOOST_SCOPE_EXIT_END
     26        BOOST_SCOPE_EXIT_TPL(&i) { ++i; } BOOST_SCOPE_EXIT_END
    2727    }
    2828    return i;
    2929}
    3030#else
    31 inline int template_f(int i)
    32 {
     31inline int template_f(int i) {
    3332    {
    34         BOOST_SCOPE_EXIT( (&i) ) { ++i; } BOOST_SCOPE_EXIT_END
     33        BOOST_SCOPE_EXIT(&i) { ++i; } BOOST_SCOPE_EXIT_END
    3534    }
    3635    return i;
Note: See TracChangeset for help on using the changeset viewer.