1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
// 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';
}
|