1
2// Copyright (C) 2006-2009, 2012 Alexander Nasonov
3// Copyright (C) 2012 Lorenzo Caminiti
4// Distributed under the Boost Software License, Version 1.0
5// (see accompanying file LICENSE_1_0.txt or a copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7// Home at http://www.boost.org/libs/scope_exit
8
9#include <boost/config.hpp>
10#if defined(BOOST_NO_CXX11_LAMBDAS)
11# error "lambda functions required"
12#elif defined(BOOST_NO_CXX11_VARIADIC_MACROS)
13# error "variadic macros required"
14#else
15
16#include <boost/scope_exit.hpp>
17#include <boost/foreach.hpp>
18#include <boost/typeof/typeof.hpp>
19#include <boost/typeof/std/vector.hpp>
20#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
21#include <boost/detail/lightweight_test.hpp>
22#include <vector>
23#include <iostream>
24#include <sstream>
25
26struct person {
27 typedef unsigned int id_t;
28 typedef unsigned int evolution_t;
29
30 id_t id;
31 evolution_t evolution;
32
33 person(void) : id(0), evolution(0) {}
34
35 friend std::ostream& operator<<(std::ostream& o, person const& p) {
36 return o << "person(" << p.id << ", " << p.evolution << ")";
37 }
38};
39BOOST_TYPEOF_REGISTER_TYPE(person)
40
41struct world {
42 world(void) : next_id_(1) {}
43 void add_person(person const& a_person);
44
45 friend std::ostream& operator<<(std::ostream& o, world const& w) {
46 o << "world(" << w.next_id_ << ", {";
47 BOOST_FOREACH(person const& p, w.persons_) {
48 o << " " << p << ", ";
49 }
50 return o << "})";
51 }
52
53private:
54 person::id_t next_id_;
55 std::vector<person> persons_;
56};
57BOOST_TYPEOF_REGISTER_TYPE(world)
58
59//[world_checkpoint_all
60void world::add_person(person const& a_person) {
61 persons_.push_back(x: a_person);
62
63 // This block must be no-throw.
64 person& p = persons_.back();
65 person::evolution_t checkpoint = p.evolution;
66 // Capture all by reference `&`, but `checkpoint` and `this` (C++11 only).
67 BOOST_SCOPE_EXIT_ALL(&, checkpoint, this) { // Use `this` (not `this_`).
68 if(checkpoint == p.evolution) this->persons_.pop_back();
69 }; // Use `;` (not `SCOPE_EXIT_END`).
70
71 // ...
72
73 checkpoint = ++p.evolution;
74
75 // Assign new identifier to the person.
76 person::id_t const prev_id = p.id;
77 p.id = next_id_++;
78 // Capture all by value `=`, but `p` (C++11 only).
79 BOOST_SCOPE_EXIT_ALL(=, &p) {
80 if(checkpoint == p.evolution) {
81 this->next_id_ = p.id;
82 p.id = prev_id;
83 }
84 };
85
86 // ...
87
88 checkpoint = ++p.evolution;
89}
90//]
91
92int main(void) {
93 person adam, eva;
94 std::ostringstream oss;
95 oss << adam;
96 std::cout << oss.str() << std::endl;
97 BOOST_TEST(oss.str() == "person(0, 0)");
98
99 oss.str(s: "");
100 oss << eva;
101 std::cout << oss.str() << std::endl;
102 BOOST_TEST(oss.str() == "person(0, 0)");
103
104 world w;
105 w.add_person(a_person: adam);
106 w.add_person(a_person: eva);
107 oss.str(s: "");
108 oss << w;
109 std::cout << oss.str() << std::endl;
110 BOOST_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })");
111
112 return boost::report_errors();
113}
114
115#endif // lambda functions and variadic macros
116
117

source code of boost/libs/scope_exit/test/world_checkpoint_all.cpp