### Complete Template Usage Example with Main Function Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_tpl Demonstrates a complete example of using BOOST_SCOPE_EXIT_TPL in a template class with a main function that tests the functionality. Creates a world container, adds a person, and verifies the population count using Boost's lightweight testing framework. ```cpp int main(void) { world w; person p; w.add_person(p); BOOST_TEST(w.population() == 1); return boost::report_errors(); } ``` -------------------------------- ### Complete Boost Scope Exit Usage Example Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_this Provides a complete working example showing how to use Boost.ScopeExit with the Boost.Typeof library. The program defines a world class that manages a vector of persons and demonstrates adding a person with automatic rollback capability. Requires variadic macros support and includes proper error checking with Boost.Test. ```C++ #include #ifdef BOOST_NO_CXX11_VARIADIC_MACROS # error "variadic macros required" #else #include #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include #include struct person {}; BOOST_TYPEOF_REGISTER_TYPE(person) struct world { void add_person(person const& a_person); size_t population(void) const { return persons_.size(); } private: std::vector persons_; }; BOOST_TYPEOF_REGISTER_TYPE(world) void world::add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); BOOST_SCOPE_EXIT(&commit, this_) { if(!commit) this_->persons_.pop_back(); } BOOST_SCOPE_EXIT_END commit = true; } int main(void) { world w; person p; w.add_person(p); BOOST_TEST(w.population() == 1); return boost::report_errors(); } #endif ``` -------------------------------- ### RAII-like Cleanup with Boost Scope Exit Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/example/scope_guard_seq Demonstrates the core functionality of Boost Scope Exit for managing resources. It shows how to define cleanup actions that execute when a scope is exited, conditionally based on a flag. This example uses C++ and the Boost library. ```cpp #include #include #include #include #include #include int main(void) { bool commit = false; std::string currency("EUR"); double rate = 1.3326; std::map rates; bool currency_rate_inserted = rates.insert(std::make_pair(currency, rate)).second; BOOST_SCOPE_EXIT( (currency_rate_inserted) (&commit) (&rates) (¤cy) ) { if(currency_rate_inserted && !commit) rates.erase(currency); } BOOST_SCOPE_EXIT_END // ... commit = true; return 0; } ``` -------------------------------- ### Scope Guard with C++11 Lambdas for Map Operations Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/alternatives Demonstrates using C++11 lambdas with `ON_BLOCK_EXIT` to achieve the same conditional map erasure as the Boost.Lambda example. This version is more readable and easier to debug than the Boost.Lambda approach. ```cpp ON_BLOCK_EXIT( [currency_rate_inserted, &commit, &rates, ¤cy]() { if(currency_rate_inserted && !commit) rates.erase(currency); } ); // ... commit = true; ``` -------------------------------- ### ScopeGuard with Boost.Lambda for Map Operations Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/alternatives Shows how to use Boost.Lambda with `ON_BLOCK_EXIT` to conditionally erase an element from a map if a transaction is not committed. This example highlights the complexity of Boost.Lambda, especially with overloaded functions. ```cpp using namespace boost::lambda; ON_BLOCK_EXIT( if_(_1) [ bind( static_cast< std::map::size_type (std::map::*)(std::string const&) >(&std::map::erase) , &rates , currency ) ] , boost::cref(commit) ); // ... commit = true; ``` -------------------------------- ### BOOST_SCOPE_EXIT macro with variable capture in C++ Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/index Demonstrates the core BOOST_SCOPE_EXIT macro usage for capturing variables and executing cleanup code when scope exits. This example shows a rollback pattern where a commit flag controls whether a resource (person object) is retained or removed from a collection. The captured variables are specified as a comma-separated list within the macro's parameter list. ```cpp void world::add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); // (1) direct action // Following block is executed when the enclosing scope exits. BOOST_SCOPE_EXIT(&commit, &persons_) { if(!commit) persons_.pop_back(); // (2) rollback action } BOOST_SCOPE_EXIT_END // ... // (3) other operations commit = true; // (4) disable rollback actions } ``` -------------------------------- ### Scope Exit with Capture by Reference (C++) Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_checkpoint_all Demonstrates using `BOOST_SCOPE_EXIT_ALL` to capture variables by reference. This is useful for modifying or cleaning up resources that are shared across scopes. The captured variables, including `this` and `checkpoint`, are accessed within the exit block to potentially revert changes if a specific condition (like `checkpoint == p.evolution`) is met. This specific example handles reverting the `persons_` vector in the `world` class. ```cpp #include #include #include struct person { typedef unsigned int id_t; typedef unsigned int evolution_t; id_t id; evolution_t evolution; person(void) : id(0), evolution(0) {} friend std::ostream& operator<<(std::ostream& o, person const& p) { return o << "person(" << p.id << ", " << p.evolution << ")"; } }; struct world { world(void) : next_id_(1) {} void add_person(person const& a_person); friend std::ostream& operator<<(std::ostream& o, world const& w) { o << "world(" << w.next_id_ << ", {"; BOOST_FOREACH(person const& p, w.persons_) { o << " " << p << ", "; } return o << "})"; } private: person::id_t next_id_; std::vector persons_; }; void world::add_person(person const& a_person) { persons_.push_back(a_person); // This block must be no-throw. person& p = persons_.back(); person::evolution_t checkpoint = p.evolution; // Capture all by reference `&`, but `checkpoint` and `this` (C++11 only). BOOST_SCOPE_EXIT_ALL(&, checkpoint, this) { // Use `this` (not `this_`). if(checkpoint == p.evolution) this->persons_.pop_back(); }; // Use `;` (not `SCOPE_EXIT_END`). // ... checkpoint = ++p.evolution; // Assign new identifier to the person. person::id_t const prev_id = p.id; p.id = next_id_++; // Capture all by value `=`, but `p` (C++11 only). BOOST_SCOPE_EXIT_ALL(=, &p) { if(checkpoint == p.evolution) { this->next_id_ = p.id; p.id = prev_id; } }; // ... checkpoint = ++p.evolution; } ``` -------------------------------- ### C++: Implement Void Scope Exit with Boost.ScopeExit Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_void Demonstrates how to use BOOST_SCOPE_EXIT to create a void scope exit in C++. This is useful for actions that need to be performed when exiting a scope, regardless of whether an exception is thrown. It captures no variables from the surrounding scope. The example shows adding a person to a vector and rolling back the addition if 'commit' is false. ```cpp #include #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include #include struct person {}; BOOST_TYPEOF_REGISTER_TYPE(person) struct world_t; BOOST_TYPEOF_REGISTER_TYPE(world_t) //[world_void struct world_t { std::vector persons; bool commit; } world; // Global variable. void add_person(person const& a_person) { world.commit = false; world.persons.push_back(a_person); BOOST_SCOPE_EXIT(void) { // No captures. if(!world.commit) world.persons.pop_back(); } BOOST_SCOPE_EXIT_END // ... world.commit = true; } //] int main(void) { person p; add_person(p); BOOST_TEST(world.persons.size() == 1); return boost::report_errors(); } ``` -------------------------------- ### Main Function Execution and Testing (C++) Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_checkpoint_all Contains the `main` function which serves as the entry point for the program. It demonstrates the usage of the `person` and `world` structures, including adding persons to the world and printing their states. It also utilizes `boost::report_errors()` for testing, asserting the expected output and state changes throughout the execution. ```cpp #include #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include #include #include #include struct person { typedef unsigned int id_t; typedef unsigned int evolution_t; id_t id; evolution_t evolution; person(void) : id(0), evolution(0) {} friend std::ostream& operator<<(std::ostream& o, person const& p) { return o << "person(" << p.id << ", " << p.evolution << ")"; } }; BOOST_TYPEOF_REGISTER_TYPE(person) struct world { world(void) : next_id_(1) {} void add_person(person const& a_person); friend std::ostream& operator<<(std::ostream& o, world const& w) { o << "world(" << w.next_id_ << ", {"; BOOST_FOREACH(person const& p, w.persons_) { o << " " << p << ", "; } return o << "})"; } private: person::id_t next_id_; std::vector persons_; }; BOOST_TYPEOF_REGISTER_TYPE(world) //[world_checkpoint_all void world::add_person(person const& a_person) { persons_.push_back(a_person); // This block must be no-throw. person& p = persons_.back(); person::evolution_t checkpoint = p.evolution; // Capture all by reference `&`, but `checkpoint` and `this` (C++11 only). BOOST_SCOPE_EXIT_ALL(&, checkpoint, this) { // Use `this` (not `this_`). if(checkpoint == p.evolution) this->persons_.pop_back(); }; // Use `;` (not `SCOPE_EXIT_END`). // ... checkpoint = ++p.evolution; // Assign new identifier to the person. person::id_t const prev_id = p.id; p.id = next_id_++; // Capture all by value `=`, but `p` (C++11 only). BOOST_SCOPE_EXIT_ALL(=, &p) { if(checkpoint == p.evolution) { this->next_id_ = p.id; p.id = prev_id; } }; // ... checkpoint = ++p.evolution; } //] int main(void) { person adam, eva; std::ostringstream oss; oss << adam; std::cout << oss.str() << std::endl; BOOST_TEST(oss.str() == "person(0, 0)"); oss.str(""); oss << eva; std::cout << oss.str() << std::endl; BOOST_TEST(oss.str() == "person(0, 0)"); world w; w.add_person(adam); w.add_person(eva); oss.str(""); oss << w; std::cout << oss.str() << std::endl; BOOST_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })"); return boost::report_errors(); } ``` -------------------------------- ### File Handling with Try-Catch and Manual Closing Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/alternatives Demonstrates a basic file handling scenario using a try-catch block where the file must be explicitly closed. This approach requires careful management of the file object's scope and state, especially in the presence of exceptions. ```cpp file passwd; try { passwd.open("/etc/passwd"); // ... passwd.close(); } catch(...) { std::clog << "could not get user info" << std::endl; if(passwd.is_open()) passwd.close(); throw; } ``` -------------------------------- ### RAII for File Management Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/alternatives Shows the standard RAII (Resource Acquisition Is Initialization) pattern for file management, where a file object's destructor handles closing the file. This is a robust and common C++ idiom for exception safety. ```cpp try { file passwd("/etc/passwd"); // ... } catch(...) { std::clog << "could not get user info" << std::endl; throw; } ``` -------------------------------- ### Resource Management with Boost.ScopeExit Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/alternatives Presents the Boost.ScopeExit solution for managing map operations, ensuring that a currency rate is erased if a transaction is not committed. This approach is concise and avoids the complexities of Boost.Lambda or manual RAII. ```cpp BOOST_SCOPE_EXIT(currency_rate_inserted, &commit, &rates, ¤cy) { if(currency_rate_inserted && !commit) rates.erase(currency); } BOOST_SCOPE_EXIT_END // ... commit = true; ``` -------------------------------- ### File Handling with Boost.ScopeExit Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/alternatives Illustrates how Boost.ScopeExit simplifies file handling by ensuring the file is closed automatically when exiting the scope, even if exceptions occur. This eliminates the need for manual `close()` calls within the try-catch block. ```cpp try { file passwd("/etc/passwd"); BOOST_SCOPE_EXIT(&passwd) { passwd.close(); } BOOST_SCOPE_EXIT_END } catch(...) { std::clog << "could not get user info" << std::endl; throw; } ``` -------------------------------- ### Example Usage of Templated Scope Exit in a Function (C++) Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/same_line_seq Demonstrates the usage of the `SCOPE_EXIT_INC_DEC_TPL` macro within a templated function `f`. This function takes two references of a templated type `T`, `x` and `delta`. A scope exit is defined to modify `x` by `delta` upon function exit, and a test is performed to assert `x`'s value. ```c++ template void f(T& x, T& delta) { SCOPE_EXIT_INC_DEC_TPL(x, delta) BOOST_TEST(x == 0); } ``` -------------------------------- ### Illustrating GCC Bug with Scope Exits in Templates (C++) Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/doxygen/reference/scope__exit_8hpp_1ab46e489b869d28c3e3e091168d2b775f This code snippet illustrates a compilation issue encountered with older GCC versions when using scope exit declarations within function templates. The problem arises from how the compiler deduces types within templates, which is addressed by the BOOST_SCOPE_EXIT_TPL macro by explicitly using `typename`. This example highlights the necessity of such workarounds for template metaprogramming. ```cpp template void f(T const& x) { int i = 0; struct local { // The issue is here: GCC may not correctly deduce these types without 'typename' typedef __typeof__(i) typeof_i; typedef __typeof__(x) typeof_x; }; // To fix this, the implementation of BOOST_SCOPE_EXIT_TPL effectively adds 'typename' // before 'local::typeof_i' and 'local::typeof_x' when needed. typedef local::typeof_i i_type; typedef local::typeof_x x_type; } int main(void) { f(0); // This call would fail to compile on affected GCC versions without the workaround return 0; } ``` -------------------------------- ### Main Function demonstrating Scope Exit Macros (C++) Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/same_line_seq The main function serves as an entry point to demonstrate the functionality of the Boost.ScopeExit library. It initializes variables, uses `SCOPE_EXIT_INC_DEC` within a block, calls the templated function `f`, and conditionally uses `SCOPE_EXIT_ALL_INC_DEC` if C++11 lambdas are available. It concludes by reporting any test errors. ```c++ int main(void) { int x = 0, delta = 10; { SCOPE_EXIT_INC_DEC(x, delta) } BOOST_TEST(x == 0); f(x, delta); #ifndef BOOST_NO_CXX11_LAMBDAS { SCOPE_EXIT_ALL_INC_DEC(x, delta) } BOOST_TEST(x == 0); #endif // LAMBDAS return boost::report_errors(); } ``` -------------------------------- ### Manual File Handling with Try-Catch Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/example/try_catch_seq Illustrates a traditional approach to resource management using try-catch blocks to ensure a file is closed. This method is more verbose and error-prone compared to using scope_exit. ```cpp #include struct file { file(void) : open_(false) {} file(char const* path) : open_(false) { open(path); } void open(char const* path) { open_ = true; } void close(void) { open_ = false; } bool is_open(void) const { return open_; } private: bool open_; }; void bad(void) { //[try_catch_bad_seq file passwd; try { passwd.open("/etc/passwd"); // ... passwd.close(); } catch(...) { std::clog << "could not get user info" << std::endl; if(passwd.is_open()) passwd.close(); throw; } //] } ``` -------------------------------- ### Smart Pointer for Object Ownership Transfer Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/alternatives Illustrates transferring ownership of a dynamically allocated object using `std::auto_ptr`. It shows how to acquire an object, add it to a container, and then release ownership to the container, ensuring proper cleanup. ```cpp std::auto_ptr superman_ptr(new superman()); persons_.push_back(superman_ptr.get()); superman_ptr.release(); // persons_ successfully took ownership ``` -------------------------------- ### RAII File Handling with Scope Exit Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/example/try_catch_seq Demonstrates safe file handling using BOOST_SCOPE_EXIT to ensure a file is closed, even if exceptions occur. This approach simplifies resource management compared to manual try-catch blocks. ```cpp #include #include struct file { file(void) : open_(false) {} file(char const* path) : open_(false) { open(path); } void open(char const* path) { open_ = true; } void close(void) { open_ = false; } bool is_open(void) const { return open_; } private: bool open_; }; void good(void) { //[try_catch_good_seq try { file passwd("/etc/passwd"); BOOST_SCOPE_EXIT( (&passwd) ) { passwd.close(); } BOOST_SCOPE_EXIT_END } catch(...) { std::clog << "could not get user info" << std::endl; throw; } //] } ``` -------------------------------- ### Include Boost Scope Exit Header Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/doxygen/reference/scope__exit_8hpp_1afc2c5bf6e868d7d8d703c64a984d38cd Shows the required header file inclusion for using BOOST_SCOPE_EXIT_END and related scope exit macros from the Boost C++ Libraries. ```cpp #include ``` -------------------------------- ### Boost Scope Exit: Main Function Test Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_checkpoint The main function demonstrates the usage of the 'world' and 'person' classes and tests the functionality of the Boost Scope Exit mechanism. It verifies the initial state of persons, the state after adding persons to the world, and ensures the output matches the expected string representations. It relies on Boost.Test for assertions. ```C++ #include #include #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include #include #include #include // ... (person and world struct definitions from previous snippet) ... int main(void) { person adam, eva; std::ostringstream oss; oss << adam; std::cout << oss.str() << std::endl; BOOST_TEST(oss.str() == "person(0, 0)"); oss.str(""); oss << eva; std::cout << oss.str() << std::endl; BOOST_TEST(oss.str() == "person(0, 0)"); world w; w.add_person(adam); w.add_person(eva); oss.str(""); oss << w; std::cout << oss.str() << std::endl; BOOST_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })"); return boost::report_errors(); } #endif // variadic macros ``` -------------------------------- ### BOOST_SCOPE_EXIT Capture List Grammar with Variadic Macros Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/doxygen/reference/scope__exit_8hpp_1ae0a86562a607889be5c08af8ad6ead1b Defines the grammar for capture lists on compilers supporting variadic macros. Supports three formats: void (no capture), comma-separated capture tuple, or Boost.Preprocessor sequence with optional reference capture using & and special this_ handling. ```cpp capture_list: void | capture_tuple | capture_sequence capture_tuple: capture, capture, ... capture_sequence: (capture) (capture) ... capture: [&]variable | this_ ``` -------------------------------- ### Boost Scope Exit Test Case in C++ Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_checkpoint_seq A test case in C++ using Boost Scope Exit and Boost.Test to verify the functionality of the `person` and `world` classes. It checks the initial state of `person` objects, the output formatting of `person` and `world` objects, and the state of the `world` object after adding persons. It utilizes `std::ostringstream` for output capture and `BOOST_TEST` for assertions. Dependencies include boost/scope_exit.hpp, boost/foreach.hpp, boost/typeof/typeof.hpp, boost/typeof/std/vector.hpp, boost/detail/lightweight_test.hpp, , and . ```cpp #include #include #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include #include #include struct person { typedef unsigned int id_t; typedef unsigned int evolution_t; id_t id; evolution_t evolution; person(void) : id(0), evolution(0) {} friend std::ostream& operator<<(std::ostream& o, person const& p) { return o << "person(" << p.id << ", " << p.evolution << ")"; } }; BOOST_TYPEOF_REGISTER_TYPE(person) struct world { world(void) : next_id_(1) {} void add_person(person const& a_person); friend std::ostream& operator<<(std::ostream& o, world const& w) { o << "world(" << w.next_id_ << ", {"; BOOST_FOREACH(person const& p, w.persons_) { o << " " << p << ", "; } return o << "})"; } private: person::id_t next_id_; std::vector persons_; }; BOOST_TYPEOF_REGISTER_TYPE(world) void world::add_person(person const& a_person) { persons_.push_back(a_person); // This block must be no-throw. person& p = persons_.back(); person::evolution_t checkpoint = p.evolution; BOOST_SCOPE_EXIT( (checkpoint) (&p) (&persons_) ) { if(checkpoint == p.evolution) persons_.pop_back(); } BOOST_SCOPE_EXIT_END // ... checkpoint = ++p.evolution; // Assign new identifier to the person. person::id_t const prev_id = p.id; p.id = next_id_++; BOOST_SCOPE_EXIT( (checkpoint) (&p) (&next_id_) (prev_id) ) { if(checkpoint == p.evolution) { next_id_ = p.id; p.id = prev_id; } } BOOST_SCOPE_EXIT_END // ... checkpoint = ++p.evolution; } int main(void) { person adam, eva; std::ostringstream oss; oss << adam; BOOST_TEST(oss.str() == "person(0, 0)"); oss.str(""); oss << eva; BOOST_TEST(oss.str() == "person(0, 0)"); world w; w.add_person(adam); w.add_person(eva); oss.str(""); oss << w; BOOST_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })"); return boost::report_errors(); } ``` -------------------------------- ### BOOST_SCOPE_EXIT Capture List Grammar Without Variadic Macros Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/doxygen/reference/scope__exit_8hpp_1ae0a86562a607889be5c08af8ad6ead1b Defines the capture list grammar for compilers without variadic macro support. Only supports void or Boost.Preprocessor sequence format, excluding comma-separated tuple syntax. ```cpp capture_list: void | capture_sequence ``` -------------------------------- ### Boost Scope Exit with Preprocessor Sequence Syntax (C++) Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/no_variadic_macros Demonstrates the Boost.Preprocessor sequence syntax for `BOOST_SCOPE_EXIT`, which is compatible with all compilers, including those without variadic macro support. This syntax uses tokens enclosed in parentheses for capture lists. ```C++ void world::add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); // (1) direct action // Following block is executed when the enclosing scope exits. BOOST_SCOPE_EXIT( (&commit) (&persons_) ) { if(!commit) persons_.pop_back(); // (2) rollback action } BOOST_SCOPE_EXIT_END // ... // (3) other operations commit = true; // (4) disable rollback actions } ``` -------------------------------- ### Custom RAII Guard for Vector Operations Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/alternatives Demonstrates a custom RAII class (`pop_back_if_not_commit`) designed to manage a vector's state, specifically to pop an element if a commit flag is not set. This illustrates building specific RAII types for complex scenarios. ```cpp persons_.push_back(a_person); pop_back_if_not_commit pop_back_if_not_commit_guard(commit, persons_); ``` ```cpp class pop_back_if_not_commit { bool commit_; std::vector& vec_; // ... ~pop_back_if_not_commit() { if(!commit_) vec_.pop_back(); } }; ``` -------------------------------- ### C++ Boost Scope Exit with Test Assertions Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_checkpoint_all_seq Demonstrates the usage of Boost Scope Exit within a test scenario, verifying object states and string representations using BOOST_TEST and std::ostringstream. It highlights the library's integration with testing frameworks. ```C++ #include #include #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include #include #include #include struct person { typedef unsigned int id_t; typedef unsigned int evolution_t; id_t id; evolution_t evolution; person(void) : id(0), evolution(0) {} friend std::ostream& operator<<(std::ostream& o, person const& p) { return o << "person(" << p.id << ", " << p.evolution << ")"; } }; BOOST_TYPEOF_REGISTER_TYPE(person) struct world { world(void) : next_id_(1) {} void add_person(person const& a_person); friend std::ostream& operator<<(std::ostream& o, world const& w) { o << "world(" << w.next_id_ << ", {"; BOOST_FOREACH(person const& p, w.persons_) { o << " " << p << ", "; } return o << "})"; } private: person::id_t next_id_; std::vector persons_; }; BOOST_TYPEOF_REGISTER_TYPE(world) void world::add_person(person const& a_person) { persons_.push_back(a_person); person& p = persons_.back(); person::evolution_t checkpoint = p.evolution; BOOST_SCOPE_EXIT_ALL( (&) (checkpoint) (this) ) { if(checkpoint == p.evolution) this->persons_.pop_back(); }; checkpoint = ++p.evolution; person::id_t const prev_id = p.id; p.id = next_id_++; BOOST_SCOPE_EXIT_ALL( (=) (&p) ) { if(checkpoint == p.evolution) { this->next_id_ = p.id; p.id = prev_id; } }; checkpoint = ++p.evolution; } int main(void) { person adam, eva; std::ostringstream oss; oss << adam; std::cout << oss.str() << std::endl; BOOST_TEST(oss.str() == "person(0, 0)"); oss.str(""); oss << eva; std::cout << oss.str() << std::endl; BOOST_TEST(oss.str() == "person(0, 0)"); world w; w.add_person(adam); w.add_person(eva); oss.str(""); oss << w; std::cout << oss.str() << std::endl; BOOST_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })"); return boost::report_errors(); } ``` -------------------------------- ### BOOST_SCOPE_EXIT C++11 Lambda Alternative Syntax Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/doxygen/reference/scope__exit_8hpp_1ae0a86562a607889be5c08af8ad6ead1b Shows enhanced capture syntax available on C++11 compilers with lambda support when BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS is defined. Allows semicolon instead of BOOST_SCOPE_EXIT_END and uses 'this' instead of 'this_'. ```cpp capture: [&]variable | this_ | this ``` -------------------------------- ### RAII with try-catch block Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/example/try_catch Demonstrates manual resource management (closing a file) within a try-catch block. This approach requires explicit calls to close() in both the normal execution path and the exception handler, making it verbose and error-prone. It highlights the need for careful exception safety. ```C++ #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include struct file { file(void) : open_(false) {} file(char const* path) : open_(false) { open(path); } void open(char const* path) { open_ = true; } void close(void) { open_ = false; } bool is_open(void) const { return open_; } private: bool open_; }; BOOST_TYPEOF_REGISTER_TYPE(file) void bad(void) { //[try_catch_bad file passwd; try { passwd.open("/etc/passwd"); // ... passwd.close(); } catch(...) { std::clog << "could not get user info" << std::endl; if(passwd.is_open()) passwd.close(); throw; } //] } void good(void) { //[try_catch_good try { file passwd("/etc/passwd"); BOOST_SCOPE_EXIT(&passwd) { passwd.close(); } BOOST_SCOPE_EXIT_END } catch(...) { std::clog << "could not get user info" << std::endl; throw; } //] } int main(void) { bad(); good(); return 0; } #endif // variadic macros ``` -------------------------------- ### Boost Scope Exit Macros for C++ Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/reference This snippet lists the primary macros provided by the Boost Scope Exit header. These macros enable the execution of specified code blocks when the current scope is exited, ensuring resource cleanup or other actions are reliably performed. They are fundamental to the library's functionality. ```cpp #include // Example usage: int main() { int x = 10; BOOST_SCOPE_EXIT(x) { // This code will execute when main() exits std::cout << "Exiting scope, x is: " << x << std::endl; } BOOST_SCOPE_EXIT_END x = 20; return 0; } ``` ```cpp BOOST_SCOPE_EXIT(capture_list) BOOST_SCOPE_EXIT_TPL(capture_list) BOOST_SCOPE_EXIT_ID(id, capture_list) BOOST_SCOPE_EXIT_ID_TPL(id, capture_list) BOOST_SCOPE_EXIT_ALL(capture_list) BOOST_SCOPE_EXIT_ALL_ID(id, capture_list) BOOST_SCOPE_EXIT_END BOOST_SCOPE_EXIT_END_ID(id) BOOST_SCOPE_EXIT_CONFIG_USE_LAMBDAS ``` -------------------------------- ### BOOST_SCOPE_EXIT_ALL Macro Declaration and Usage (C++) Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/doxygen/reference/scope__exit_8hpp_1abe3e0c14285fc6303c6cd46884912608 Demonstrates the declaration and usage of the BOOST_SCOPE_EXIT_ALL macro. This macro captures all variables in scope by reference or value, following C++11 lambda capture syntax. The scope exit body must be terminated with a semicolon. ```cpp // In header: BOOST_SCOPE_EXIT_ALL(capture_list) { // Some local scope. ... BOOST_SCOPE_EXIT_ALL(&) { // Captures all variables by reference (C++11 only). // Body code. }; // Use ';' instead of BOOST_SCOPE_EXIT_END (C++11 only). ... } // Example with capture by value int x = 10; BOOST_SCOPE_EXIT_ALL(=) { // x is captured by value // ... }; // Example with explicit capture list (if variadic macros are supported) BOOST_SCOPE_EXIT_ALL(=, &x, y) { // Captures x by value, y by reference // ... }; ``` -------------------------------- ### C++: Scope Exit with Checkpointing and Rollback Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/tutorial Illustrates advanced usage of Boost.ScopeExit for managing intermediate states and rolling back to a previous state using a checkpoint mechanism. It captures variables by value and reference to compare states and perform conditional rollbacks. ```cpp void world::add_person(person const& a_person) { persons_.push_back(a_person); // This block must be no-throw. person& p = persons_.back(); person::evolution_t checkpoint = p.evolution; BOOST_SCOPE_EXIT(checkpoint, &p, &persons_) { if(checkpoint == p.evolution) persons_.pop_back(); } BOOST_SCOPE_EXIT_END // ... checkpoint = ++p.evolution; // Assign new identifier to the person. person::id_t const prev_id = p.id; p.id = next_id_++; BOOST_SCOPE_EXIT(checkpoint, &p, &next_id_, prev_id) { if(checkpoint == p.evolution) { next_id_ = p.id; p.id = prev_id; } } BOOST_SCOPE_EXIT_END // ... checkpoint = ++p.evolution; } ``` -------------------------------- ### Boost Scope Exit with Comma-Separated Syntax (C++) Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/no_variadic_macros Illustrates the comma-separated syntax for `BOOST_SCOPE_EXIT`, which requires variadic macro support found in modern C++11 compilers. This syntax is generally preferred for its readability when variadic macros are available. ```C++ void world::add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); // (1) direct action // Following block is executed when the enclosing scope exits. BOOST_SCOPE_EXIT(&commit, &persons_) { if(!commit) persons_.pop_back(); // (2) rollback action } BOOST_SCOPE_EXIT_END // ... // (3) other operations commit = true; // (4) disable rollback actions } ``` -------------------------------- ### C++ Boost Scope Exit for Identifier and State Restoration Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_checkpoint_all_seq Illustrates using Boost's SCOPE_EXIT macro with capture-by-value and capture-by-reference to restore the previous identifier and state of a person object if an exit occurs before subsequent operations complete. This ensures data integrity. ```C++ #include #include #include struct person { typedef unsigned int id_t; typedef unsigned int evolution_t; id_t id; evolution_t evolution; person(void) : id(0), evolution(0) {} friend std::ostream& operator<<(std::ostream& o, person const& p) { return o << "person(" << p.id << ", " << p.evolution << ")"; } }; struct world { world(void) : next_id_(1) {} void add_person(person const& a_person); friend std::ostream& operator<<(std::ostream& o, world const& w) { o << "world(" << w.next_id_ << ", {"; BOOST_FOREACH(person const& p, w.persons_) { o << " " << p << ", "; } return o << "})"; } private: person::id_t next_id_; std::vector persons_; }; void world::add_person(person const& a_person) { persons_.push_back(a_person); person& p = persons_.back(); person::evolution_t checkpoint = p.evolution; // This scope exit restores the person to the persons_ list if evolution hasn't changed. BOOST_SCOPE_EXIT_ALL( (&) (checkpoint) (this) ) { if(checkpoint == p.evolution) this->persons_.pop_back(); }; checkpoint = ++p.evolution; person::id_t const prev_id = p.id; p.id = next_id_++; // This scope exit restores the person's ID and next_id_ if evolution hasn't changed. BOOST_SCOPE_EXIT_ALL( (=) (&p) ) { if(checkpoint == p.evolution) { this->next_id_ = p.id; p.id = prev_id; } }; checkpoint = ++p.evolution; } ``` -------------------------------- ### RAII with BOOST_SCOPE_EXIT_TPL in C++ Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_tpl_seq Demonstrates the use of the `BOOST_SCOPE_EXIT_TPL` macro for implementing RAII (Resource Acquisition Is Initialization) in C++. It captures a boolean flag `commit` and the `this_` pointer to manage a `std::vector` within the `world` class. If `commit` remains false upon scope exit, the last added person is removed from the `persons_` vector, ensuring the vector's state is consistent. ```cpp #include #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include #include struct person {}; BOOST_TYPEOF_REGISTER_TYPE(person) template struct world { void add_person(Person const& a_person); size_t population(void) const { return persons_.size(); } private: std::vector persons_; }; BOOST_TYPEOF_REGISTER_TEMPLATE(world, 1) template void world::add_person(Person const& a_person) { bool commit = false; persons_.push_back(a_person); BOOST_SCOPE_EXIT_TPL( (&commit) (this_) ) { if(!commit) this_->persons_.pop_back(); } BOOST_SCOPE_EXIT_END // ... potentially some operations that might throw exceptions ... commit = true; } int main(void) { world w; person p; w.add_person(p); BOOST_TEST(w.population() == 1); return boost::report_errors(); } ``` -------------------------------- ### C++ Scope Exit with Lambda for Resource Management Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world_checkpoint_all_seq Demonstrates using Boost's SCOPE_EXIT macro with a lambda function to ensure a person is removed from a world's persons list if the current evolution checkpoint matches. This is typically used for no-throw operations to maintain consistent state. ```C++ #include #include #include struct person { typedef unsigned int id_t; typedef unsigned int evolution_t; id_t id; evolution_t evolution; person(void) : id(0), evolution(0) {} friend std::ostream& operator<<(std::ostream& o, person const& p) { return o << "person(" << p.id << ", " << p.evolution << ")"; } }; struct world { world(void) : next_id_(1) {} void add_person(person const& a_person); friend std::ostream& operator<<(std::ostream& o, world const& w) { o << "world(" << w.next_id_ << ", {"; BOOST_FOREACH(person const& p, w.persons_) { o << " " << p << ", "; } return o << "})"; } private: person::id_t next_id_; std::vector persons_; }; void world::add_person(person const& a_person) { persons_.push_back(a_person); // This block must be no-throw. person& p = persons_.back(); person::evolution_t checkpoint = p.evolution; BOOST_SCOPE_EXIT_ALL( (&) (checkpoint) (this) ) { if(checkpoint == p.evolution) this->persons_.pop_back(); }; // ... checkpoint = ++p.evolution; // Assign new identifier to the person. person::id_t const prev_id = p.id; p.id = next_id_++; BOOST_SCOPE_EXIT_ALL( (=) (&p) ) { if(checkpoint == p.evolution) { this->next_id_ = p.id; p.id = prev_id; } }; // ... checkpoint = ++p.evolution; } ``` -------------------------------- ### Scope Exit with Rollback using Boost.ScopeExit Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/test/world Demonstrates using BOOST_SCOPE_EXIT to define a rollback action (popping from a vector) that is executed if a commit flag is not set before the scope ends. This pattern is useful for managing resources where operations might fail and require cleanup. ```cpp #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include #include struct person {}; BOOST_TYPEOF_REGISTER_TYPE(person) struct world { void add_person(person const& a_person); size_t population(void) const { return persons_.size(); } private: std::vector persons_; }; BOOST_TYPEOF_REGISTER_TYPE(world) //[world void world::add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); // (1) direct action // Following block is executed when the enclosing scope exits. BOOST_SCOPE_EXIT(&commit, &persons_) { if(!commit) persons_.pop_back(); // (2) rollback action } BOOST_SCOPE_EXIT_END // ... // (3) other operations commit = true; // (4) disable rollback actions } //] int main(void) { world w; person p; w.add_person(p); BOOST_TEST(w.population() == 1); return boost::report_errors(); } #endif // variadic macros ``` -------------------------------- ### RAII Scope Exit with C++11 Lambda Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/example/world_cxx11_lambda Implements a scope_exit RAII wrapper that accepts a std::function (typically a C++11 lambda) to execute cleanup code upon scope exit. It captures necessary variables and context, like 'this', to perform actions such as removing elements from a vector if a commit flag is not set. ```cpp // Copyright (C) 2006-2009, 2012 Alexander Nasonov // Copyright (C) 2012 Lorenzo Caminiti // Distributed under the Boost Software License, Version 1.0 // (see accompanying file LICENSE_1_0.txt or a copy at // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/scope_exit #include #ifdef BOOST_NO_CXX11_LAMBDAS # error "lambda functions required" #else #include #include #include struct person {}; struct world { void add_person(person const& a_person); std::vector persons_; }; //[world_cxx11_lambda struct scope_exit { scope_exit(std::function f) : f_(f) {} ~scope_exit(void) { f_(); } private: std::function f_; }; void world::add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); scope_exit on_exit1([&commit, this](void) { // Use C++11 lambda. if(!commit) persons_.pop_back(); // `persons_` via captured `this`. }); // ... commit = true; } //] int main(void) { world w; person p; w.add_person(p); BOOST_TEST(w.persons_.size() == 1); return boost::report_errors(); } #endif // LAMBDAS ``` -------------------------------- ### Capture All Variables (C++11) with BOOST_SCOPE_EXIT_ALL Source: https://www.boost.org/doc/libs/latest/libs/scope_exit/doc/html/scope_exit/tutorial Shows how to use BOOST_SCOPE_EXIT_ALL on C++11 compliant compilers to capture all variables in scope implicitly, either by reference ('&') or by value ('='). Specific variables can be explicitly captured, overriding the default behavior. This macro follows C++11 lambda syntax and uses 'this' (not 'this_') to refer to the object. ```cpp void world::add_person(person const& a_person) { persons_.push_back(a_person); // This block must be no-throw. person& p = persons_.back(); person::evolution_t checkpoint = p.evolution; // Capture all by reference '&', but 'checkpoint' and 'this' (C++11 only). BOOST_SCOPE_EXIT_ALL(&, checkpoint, this) { // Use 'this' (not 'this_'). if(checkpoint == p.evolution) this->persons_.pop_back(); }; // Use ';' (not 'SCOPE_EXIT_END'). // ... checkpoint = ++p.evolution; // Assign new identifier to the person. person::id_t const prev_id = p.id; p.id = next_id_++; // Capture all by value '=', but 'p' (C++11 only). BOOST_SCOPE_EXIT_ALL(=, &p) { if(checkpoint == p.evolution) { this->next_id_ = p.id; p.id = prev_id; } }; // ... checkpoint = ++p.evolution; } ```