• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 // Copyright (C) 2009-2012 Lorenzo Caminiti
3 // Distributed under the Boost Software License, Version 1.0
4 // (see accompanying file LICENSE_1_0.txt or a copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 // Home at http://www.boost.org/libs/local_function
7 
8 #include "scope_exit.hpp"
9 #include <boost/foreach.hpp>
10 #include <boost/typeof/typeof.hpp>
11 #include <boost/typeof/std/vector.hpp>
12 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
13 #include <boost/detail/lightweight_test.hpp>
14 #include <vector>
15 #include <iostream>
16 #include <sstream>
17 
18 class person {
19     friend class world;
20 public:
21     typedef unsigned int id_t;
22     typedef unsigned int evolution_t;
23 
person(void)24     person(void): id_(0), evolution_(0) {}
25 
operator <<(std::ostream & o,person const & p)26     friend std::ostream& operator<<(std::ostream& o, person const& p) {
27         return o << "person(" << p.id_ << ", " << p.evolution_ << ")";
28     }
29 private:
30     id_t id_;
31     evolution_t evolution_;
32 };
33 BOOST_TYPEOF_REGISTER_TYPE(person)
34 
35 class world {
36 public:
37     typedef unsigned int id_t;
38 
world(void)39     world(void): next_id_(1) {}
40 
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 private:
51     id_t next_id_;
52     std::vector<person> persons_;
53 };
BOOST_TYPEOF_REGISTER_TYPE(world)54 BOOST_TYPEOF_REGISTER_TYPE(world)
55 
56 void world::add_person(person const& a_person) {
57     persons_.push_back(a_person);
58 
59     // This block must be no-throw.
60     //[scope_exit
61     person& p = persons_.back();
62     person::evolution_t checkpoint = p.evolution_;
63 
64     SCOPE_EXIT(const bind checkpoint, const bind& p, bind this_) {
65         if (checkpoint == p.evolution_) this_->persons_.pop_back();
66     } SCOPE_EXIT_END
67     //]
68 
69     // ...
70 
71     checkpoint = ++p.evolution_;
72 
73     // Assign new id to the person.
74     world::id_t const prev_id = p.id_;
75     p.id_ = next_id_++;
76     SCOPE_EXIT(const bind checkpoint, const bind prev_id, bind& p,
77             bind& next_id_) {
78         if (checkpoint == p.evolution_) {
79             next_id_ = p.id_;
80             p.id_ = prev_id;
81         }
82     } SCOPE_EXIT_END
83 
84     // ...
85 
86     checkpoint = ++p.evolution_;
87 }
88 
main(void)89 int main(void) {
90     person adam, eva;
91     std::ostringstream oss;
92     oss << adam;
93     std::cout << oss.str() << std::endl;
94     BOOST_TEST(oss.str() == "person(0, 0)");
95 
96     oss.str("");
97     oss << eva;
98     std::cout << oss.str() << std::endl;
99     BOOST_TEST(oss.str() == "person(0, 0)");
100 
101     world w;
102     w.add_person(adam);
103     w.add_person(eva);
104     oss.str("");
105     oss << w;
106     std::cout << oss.str() << std::endl;
107     BOOST_TEST(oss.str() == "world(3, { person(1, 2),  person(2, 2), })");
108     return boost::report_errors();
109 }
110 
111