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_VARIADIC_MACROS
11 # error "variadic macros 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
24 struct person {
25 typedef unsigned int id_t;
26 typedef unsigned int evolution_t;
27
28 id_t id;
29 evolution_t evolution;
30
personperson31 person(void) : id(0), evolution(0) {}
32
operator <<(std::ostream & o,person const & p)33 friend std::ostream& operator<<(std::ostream& o, person const& p) {
34 return o << "person(" << p.id << ", " << p.evolution << ")";
35 }
36 };
37 BOOST_TYPEOF_REGISTER_TYPE(person)
38
39 struct world {
worldworld40 world(void) : next_id_(1) {}
41 void add_person(person const& a_person);
42
operator <<(std::ostream & o,world const & w)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
51 private:
52 person::id_t next_id_;
53 std::vector<person> persons_;
54 };
BOOST_TYPEOF_REGISTER_TYPE(world)55 BOOST_TYPEOF_REGISTER_TYPE(world)
56
57 //[world_checkpoint
58 void world::add_person(person const& a_person) {
59 persons_.push_back(a_person);
60
61 // This block must be no-throw.
62 person& p = persons_.back();
63 person::evolution_t checkpoint = p.evolution;
64 BOOST_SCOPE_EXIT(checkpoint, &p, &persons_) {
65 if(checkpoint == p.evolution) persons_.pop_back();
66 } BOOST_SCOPE_EXIT_END
67
68 // ...
69
70 checkpoint = ++p.evolution;
71
72 // Assign new identifier to the person.
73 person::id_t const prev_id = p.id;
74 p.id = next_id_++;
75 BOOST_SCOPE_EXIT(checkpoint, &p, &next_id_, prev_id) {
76 if(checkpoint == p.evolution) {
77 next_id_ = p.id;
78 p.id = prev_id;
79 }
80 } BOOST_SCOPE_EXIT_END
81
82 // ...
83
84 checkpoint = ++p.evolution;
85 }
86 //]
87
main(void)88 int main(void) {
89 person adam, eva;
90 std::ostringstream oss;
91 oss << adam;
92 std::cout << oss.str() << std::endl;
93 BOOST_TEST(oss.str() == "person(0, 0)");
94
95 oss.str("");
96 oss << eva;
97 std::cout << oss.str() << std::endl;
98 BOOST_TEST(oss.str() == "person(0, 0)");
99
100 world w;
101 w.add_person(adam);
102 w.add_person(eva);
103 oss.str("");
104 oss << w;
105 std::cout << oss.str() << std::endl;
106 BOOST_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })");
107
108 return boost::report_errors();
109 }
110
111 #endif // variadic macros
112
113