world_checkpoint_seq.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // Copyright (C) 2006-2009, 2012 Alexander Nasonov
  2. // Copyright (C) 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/scope_exit
  7. #include <boost/scope_exit.hpp>
  8. #include <boost/foreach.hpp>
  9. #include <boost/typeof/typeof.hpp>
  10. #include <boost/typeof/std/vector.hpp>
  11. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  12. #include <boost/detail/lightweight_test.hpp>
  13. #include <vector>
  14. #include <sstream>
  15. struct person {
  16. typedef unsigned int id_t;
  17. typedef unsigned int evolution_t;
  18. id_t id;
  19. evolution_t evolution;
  20. person(void) : id(0), evolution(0) {}
  21. friend std::ostream& operator<<(std::ostream& o, person const& p) {
  22. return o << "person(" << p.id << ", " << p.evolution << ")";
  23. }
  24. };
  25. BOOST_TYPEOF_REGISTER_TYPE(person)
  26. struct world {
  27. world(void) : next_id_(1) {}
  28. void add_person(person const& a_person);
  29. friend std::ostream& operator<<(std::ostream& o, world const& w) {
  30. o << "world(" << w.next_id_ << ", {";
  31. BOOST_FOREACH(person const& p, w.persons_) {
  32. o << " " << p << ", ";
  33. }
  34. return o << "})";
  35. }
  36. private:
  37. person::id_t next_id_;
  38. std::vector<person> persons_;
  39. };
  40. BOOST_TYPEOF_REGISTER_TYPE(world)
  41. void world::add_person(person const& a_person) {
  42. persons_.push_back(a_person);
  43. // This block must be no-throw.
  44. person& p = persons_.back();
  45. person::evolution_t checkpoint = p.evolution;
  46. BOOST_SCOPE_EXIT( (checkpoint) (&p) (&persons_) ) {
  47. if(checkpoint == p.evolution) persons_.pop_back();
  48. } BOOST_SCOPE_EXIT_END
  49. // ...
  50. checkpoint = ++p.evolution;
  51. // Assign new identifier to the person.
  52. person::id_t const prev_id = p.id;
  53. p.id = next_id_++;
  54. BOOST_SCOPE_EXIT( (checkpoint) (&p) (&next_id_) (prev_id) ) {
  55. if(checkpoint == p.evolution) {
  56. next_id_ = p.id;
  57. p.id = prev_id;
  58. }
  59. } BOOST_SCOPE_EXIT_END
  60. // ...
  61. checkpoint = ++p.evolution;
  62. }
  63. int main(void) {
  64. person adam, eva;
  65. std::ostringstream oss;
  66. oss << adam;
  67. BOOST_TEST(oss.str() == "person(0, 0)");
  68. oss.str("");
  69. oss << eva;
  70. BOOST_TEST(oss.str() == "person(0, 0)");
  71. world w;
  72. w.add_person(adam);
  73. w.add_person(eva);
  74. oss.str("");
  75. oss << w;
  76. BOOST_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })");
  77. return boost::report_errors();
  78. }