world_checkpoint_all.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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/config.hpp>
  8. #if defined(BOOST_NO_CXX11_LAMBDAS)
  9. # error "lambda functions required"
  10. #elif defined(BOOST_NO_CXX11_VARIADIC_MACROS)
  11. # error "variadic macros required"
  12. #else
  13. #include <boost/scope_exit.hpp>
  14. #include <boost/foreach.hpp>
  15. #include <boost/typeof/typeof.hpp>
  16. #include <boost/typeof/std/vector.hpp>
  17. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  18. #include <boost/detail/lightweight_test.hpp>
  19. #include <vector>
  20. #include <iostream>
  21. #include <sstream>
  22. struct person {
  23. typedef unsigned int id_t;
  24. typedef unsigned int evolution_t;
  25. id_t id;
  26. evolution_t evolution;
  27. person(void) : id(0), evolution(0) {}
  28. friend std::ostream& operator<<(std::ostream& o, person const& p) {
  29. return o << "person(" << p.id << ", " << p.evolution << ")";
  30. }
  31. };
  32. BOOST_TYPEOF_REGISTER_TYPE(person)
  33. struct world {
  34. world(void) : next_id_(1) {}
  35. void add_person(person const& a_person);
  36. friend std::ostream& operator<<(std::ostream& o, world const& w) {
  37. o << "world(" << w.next_id_ << ", {";
  38. BOOST_FOREACH(person const& p, w.persons_) {
  39. o << " " << p << ", ";
  40. }
  41. return o << "})";
  42. }
  43. private:
  44. person::id_t next_id_;
  45. std::vector<person> persons_;
  46. };
  47. BOOST_TYPEOF_REGISTER_TYPE(world)
  48. //[world_checkpoint_all
  49. void world::add_person(person const& a_person) {
  50. persons_.push_back(a_person);
  51. // This block must be no-throw.
  52. person& p = persons_.back();
  53. person::evolution_t checkpoint = p.evolution;
  54. // Capture all by reference `&`, but `checkpoint` and `this` (C++11 only).
  55. BOOST_SCOPE_EXIT_ALL(&, checkpoint, this) { // Use `this` (not `this_`).
  56. if(checkpoint == p.evolution) this->persons_.pop_back();
  57. }; // Use `;` (not `SCOPE_EXIT_END`).
  58. // ...
  59. checkpoint = ++p.evolution;
  60. // Assign new identifier to the person.
  61. person::id_t const prev_id = p.id;
  62. p.id = next_id_++;
  63. // Capture all by value `=`, but `p` (C++11 only).
  64. BOOST_SCOPE_EXIT_ALL(=, &p) {
  65. if(checkpoint == p.evolution) {
  66. this->next_id_ = p.id;
  67. p.id = prev_id;
  68. }
  69. };
  70. // ...
  71. checkpoint = ++p.evolution;
  72. }
  73. //]
  74. int main(void) {
  75. person adam, eva;
  76. std::ostringstream oss;
  77. oss << adam;
  78. std::cout << oss.str() << std::endl;
  79. BOOST_TEST(oss.str() == "person(0, 0)");
  80. oss.str("");
  81. oss << eva;
  82. std::cout << oss.str() << std::endl;
  83. BOOST_TEST(oss.str() == "person(0, 0)");
  84. world w;
  85. w.add_person(adam);
  86. w.add_person(eva);
  87. oss.str("");
  88. oss << w;
  89. std::cout << oss.str() << std::endl;
  90. BOOST_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })");
  91. return boost::report_errors();
  92. }
  93. #endif // lambda functions and variadic macros