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#ifdef BOOST_NO_CXX11_LAMBDAS
11# error "lambda functions required"
12#else
13
14#include <boost/scope_exit.hpp>
15#include <boost/foreach.hpp>
16#include <boost/typeof/typeof.hpp>
17#include <boost/typeof/std/vector.hpp>
18#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
19#include <boost/detail/lightweight_test.hpp>
20#include <vector>
21#include <iostream>
22#include <sstream>
23
24struct person {
25 typedef unsigned int id_t;
26 typedef unsigned int evolution_t;
27
28 id_t id;
29 evolution_t evolution;
30
31 person(void) : id(0), evolution(0) {}
32
33 friend std::ostream& operator<<(std::ostream& o, person const& p) {
34 return o << "person(" << p.id << ", " << p.evolution << ")";
35 }
36};
37BOOST_TYPEOF_REGISTER_TYPE(person)
38
39struct world {
40 world(void) : next_id_(1) {}
41 void add_person(person const& a_person);
42
43 friend std::ostream& operator<<(std::ostream& o, world const& w) {
44 o << "world(" << w.next_id_ << ", {";
45 BOOST_FOREACH(person const& p, w.persons_) {
46 o << " " << p << ", ";
47 }
48 return o << "})";
49 }
50
51private:
52 person::id_t next_id_;
53 std::vector<person> persons_;
54};
55BOOST_TYPEOF_REGISTER_TYPE(world)
56
57void world::add_person(person const& a_person) {
58 persons_.push_back(x: a_person);
59
60 // This block must be no-throw.
61 person& p = persons_.back();
62 person::evolution_t checkpoint = p.evolution;
63 BOOST_SCOPE_EXIT_ALL( (&) (checkpoint) (this) ) {
64 if(checkpoint == p.evolution) this->persons_.pop_back();
65 };
66
67 // ...
68
69 checkpoint = ++p.evolution;
70
71 // Assign new identifier to the person.
72 person::id_t const prev_id = p.id;
73 p.id = next_id_++;
74 BOOST_SCOPE_EXIT_ALL( (=) (&p) ) {
75 if(checkpoint == p.evolution) {
76 this->next_id_ = p.id;
77 p.id = prev_id;
78 }
79 };
80
81 // ...
82
83 checkpoint = ++p.evolution;
84}
85
86int main(void) {
87 person adam, eva;
88 std::ostringstream oss;
89 oss << adam;
90 std::cout << oss.str() << std::endl;
91 BOOST_TEST(oss.str() == "person(0, 0)");
92
93 oss.str(s: "");
94 oss << eva;
95 std::cout << oss.str() << std::endl;
96 BOOST_TEST(oss.str() == "person(0, 0)");
97
98 world w;
99 w.add_person(a_person: adam);
100 w.add_person(a_person: eva);
101 oss.str(s: "");
102 oss << w;
103 std::cout << oss.str() << std::endl;
104 BOOST_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })");
105
106 return boost::report_errors();
107}
108
109#endif // variadic macros
110
111

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