• 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 #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 
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 void world::add_person(person const& a_person) {
58     persons_.push_back(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 
main(void)86 int 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("");
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(adam);
100     w.add_person(eva);
101     oss.str("");
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