blob: 2117f6395cf8a7868c20e2dfd2c404f70a350375 [file] [log] [blame]
// 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';
}