• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
26 struct person {
27     typedef unsigned int id_t;
28     typedef unsigned int evolution_t;
29 
30     id_t id;
31     evolution_t evolution;
32 
personperson33     person(void) : id(0), evolution(0) {}
34 
operator <<(std::ostream & o,person const & p)35     friend std::ostream& operator<<(std::ostream& o, person const& p) {
36         return o << "person(" << p.id << ", " << p.evolution << ")";
37     }
38 };
39 BOOST_TYPEOF_REGISTER_TYPE(person)
40 
41 struct world {
worldworld42     world(void) : next_id_(1) {}
43     void add_person(person const& a_person);
44 
operator <<(std::ostream & o,world const & w)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 
53 private:
54     person::id_t next_id_;
55     std::vector<person> persons_;
56 };
BOOST_TYPEOF_REGISTER_TYPE(world)57 BOOST_TYPEOF_REGISTER_TYPE(world)
58 
59 //[world_checkpoint_all
60 void world::add_person(person const& a_person) {
61     persons_.push_back(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 
main(void)92 int 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("");
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(adam);
106     w.add_person(eva);
107     oss.str("");
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