// Copyright Alexander Nasonov 2009 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include <vector> #include <ostream> #include <boost/foreach.hpp> #include <boost/scope_exit.hpp> // The following is required for typeof emulation mode: #include <boost/typeof/typeof.hpp> #include <boost/typeof/std/vector.hpp> #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() class World; class Person { friend class World; public: typedef unsigned int id_t; typedef unsigned int evolution_t; Person() : m_id(0) , m_evolution(0) {} friend std::ostream& operator<<(std::ostream& o, Person const& p) { return o << "Person(" << p.m_id << ", " << p.m_evolution << ')'; } private: id_t m_id; evolution_t m_evolution; }; BOOST_TYPEOF_REGISTER_TYPE(Person) class World { public: typedef unsigned int id_t; World() : m_next_id(1) {} void addPerson(Person const& aPerson); friend std::ostream& operator<<(std::ostream& o, World const& w) { o << "World(" << w.m_next_id << ", {"; BOOST_FOREACH(Person const& p, w.m_persons) { o << ' ' << p << ','; } return o << "})"; } private: id_t m_next_id; std::vector<Person> m_persons; }; BOOST_TYPEOF_REGISTER_TYPE(World) void World::addPerson(Person const& aPerson) { m_persons.push_back(aPerson); // This block must be no-throw Person& person = m_persons.back(); Person::evolution_t checkpoint = person.m_evolution; BOOST_SCOPE_EXIT( (checkpoint)(&person)(&m_persons) ) { if(checkpoint == person.m_evolution) m_persons.pop_back(); } BOOST_SCOPE_EXIT_END // ... checkpoint = ++person.m_evolution; // Assign new id to the person World::id_t const prev_id = person.m_id; person.m_id = m_next_id++; BOOST_SCOPE_EXIT( (checkpoint)(&person)(&m_next_id)(prev_id) ) { if(checkpoint == person.m_evolution) { m_next_id = person.m_id; person.m_id = prev_id; } } BOOST_SCOPE_EXIT_END // ... checkpoint = ++person.m_evolution; } #include <iostream> int main() { Person adam, eva; std::cout << adam << '\n'; std::cout << eva << '\n'; World w; w.addPerson(adam); w.addPerson(eva); std::cout << w << '\n'; }