customer_manager.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright (C) 2008-2018 Lorenzo Caminiti
  2. // Distributed under the Boost Software License, Version 1.0 (see accompanying
  3. // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
  4. // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
  5. //[mitchell02_customer_manager
  6. #include <boost/contract.hpp>
  7. #include <string>
  8. #include <map>
  9. #include <utility>
  10. #include <cassert>
  11. // Basic customer information.
  12. struct customer_info {
  13. friend class customer_manager;
  14. typedef std::string identifier;
  15. identifier id;
  16. explicit customer_info(identifier const& _id) :
  17. id(_id), name_(), address_(), birthday_() {}
  18. private:
  19. std::string name_;
  20. std::string address_;
  21. std::string birthday_;
  22. };
  23. // Manage customers.
  24. class customer_manager {
  25. friend class boost::contract::access;
  26. void invariant() const {
  27. BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count.
  28. }
  29. public:
  30. /* Creation */
  31. customer_manager() {
  32. // Check invariants.
  33. boost::contract::check c = boost::contract::constructor(this);
  34. }
  35. virtual ~customer_manager() {
  36. // Check invariants.
  37. boost::contract::check c = boost::contract::destructor(this);
  38. }
  39. /* Basic Queries */
  40. int count() const {
  41. // Check invariants.
  42. boost::contract::check c = boost::contract::public_function(this);
  43. return customers_.size();
  44. }
  45. bool id_active(customer_info::identifier const& id) const {
  46. // Check invariants.
  47. boost::contract::check c = boost::contract::public_function(this);
  48. return customers_.find(id) != customers_.cend();
  49. }
  50. /* Derived Queries */
  51. std::string const& name_for(customer_info::identifier const& id) const {
  52. boost::contract::check c = boost::contract::public_function(this)
  53. .precondition([&] {
  54. BOOST_CONTRACT_ASSERT(id_active(id)); // Active.
  55. })
  56. ;
  57. // Find != end because of preconditions (no defensive programming).
  58. return customers_.find(id)->second.name_;
  59. }
  60. /* Commands */
  61. void add(customer_info const& info) {
  62. boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count());
  63. boost::contract::check c = boost::contract::public_function(this)
  64. .precondition([&] {
  65. // Not already active.
  66. BOOST_CONTRACT_ASSERT(!id_active(info.id));
  67. })
  68. .postcondition([&] {
  69. BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // Count inc.
  70. BOOST_CONTRACT_ASSERT(id_active(info.id)); // Activated.
  71. })
  72. ;
  73. customers_.insert(std::make_pair(info.id, customer(info)));
  74. }
  75. void set_name(customer_info::identifier const& id,
  76. std::string const& name) {
  77. boost::contract::check c = boost::contract::public_function(this)
  78. .precondition([&] {
  79. BOOST_CONTRACT_ASSERT(id_active(id)); // Already active.
  80. })
  81. .postcondition([&] {
  82. BOOST_CONTRACT_ASSERT(name_for(id) == name); // Name set.
  83. })
  84. ;
  85. // Find != end because of precondition (no defensive programming).
  86. customers_.find(id)->second.name_ = name;
  87. }
  88. private:
  89. class agent {}; // Customer agent.
  90. struct customer : customer_info {
  91. agent managing_agent;
  92. std::string last_contact;
  93. explicit customer(customer_info const& info) : customer_info(info),
  94. managing_agent(), last_contact() {}
  95. };
  96. std::map<customer_info::identifier, customer> customers_;
  97. };
  98. int main() {
  99. customer_manager m;
  100. customer_info const js("john_smith_123");
  101. m.add(js);
  102. m.set_name(js.id, "John Smith");
  103. assert(m.name_for(js.id) == "John Smith");
  104. assert(m.count() == 1);
  105. assert(m.id_active(js.id));
  106. return 0;
  107. }
  108. //]