dictionary.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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_dictionary
  6. #include <boost/contract.hpp>
  7. #include <utility>
  8. #include <map>
  9. #include <cassert>
  10. template<typename K, typename T>
  11. class dictionary {
  12. friend class boost::contract::access;
  13. void invariant() const {
  14. BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count.
  15. }
  16. public:
  17. /* Creation */
  18. // Create empty dictionary.
  19. dictionary() {
  20. boost::contract::check c = boost::contract::constructor(this)
  21. .postcondition([&] {
  22. BOOST_CONTRACT_ASSERT(count() == 0); // Empty.
  23. })
  24. ;
  25. }
  26. // Destroy dictionary.
  27. virtual ~dictionary() {
  28. // Check invariants.
  29. boost::contract::check c = boost::contract::destructor(this);
  30. }
  31. /* Basic Queries */
  32. // Number of key entries.
  33. int count() const {
  34. // Check invariants.
  35. boost::contract::check c = boost::contract::public_function(this);
  36. return items_.size();
  37. }
  38. // Has entry for key?
  39. bool has(K const& key) const {
  40. bool result;
  41. boost::contract::check c = boost::contract::public_function(this)
  42. .postcondition([&] {
  43. // Empty has no key.
  44. if(count() == 0) BOOST_CONTRACT_ASSERT(!result);
  45. })
  46. ;
  47. return result = (items_.find(key) != items_.end());
  48. }
  49. // Value for a given key.
  50. T const& value_for(K const& key) const {
  51. boost::contract::check c = boost::contract::public_function(this)
  52. .precondition([&] {
  53. BOOST_CONTRACT_ASSERT(has(key)); // Has key.
  54. })
  55. ;
  56. // Find != end because of precondition (no defensive programming).
  57. return items_.find(key)->second;
  58. }
  59. /* Commands */
  60. // Add value of a given key.
  61. void put(K const& key, T const& value) {
  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. BOOST_CONTRACT_ASSERT(!has(key)); // Has not key already.
  66. })
  67. .postcondition([&] {
  68. BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // Count inc.
  69. BOOST_CONTRACT_ASSERT(has(key)); // Has key.
  70. // Value set for key.
  71. BOOST_CONTRACT_ASSERT(value_for(key) == value);
  72. })
  73. ;
  74. items_.insert(std::make_pair(key, value));
  75. }
  76. // Remove value for given key.
  77. void remove(K const& key) {
  78. boost::contract::old_ptr<int> old_count = BOOST_CONTRACT_OLDOF(count());
  79. boost::contract::check c = boost::contract::public_function(this)
  80. .precondition([&] {
  81. BOOST_CONTRACT_ASSERT(has(key)); // Has key.
  82. })
  83. .postcondition([&] {
  84. BOOST_CONTRACT_ASSERT(count() == *old_count - 1); // Count dec.
  85. BOOST_CONTRACT_ASSERT(!has(key)); // Has not key.
  86. })
  87. ;
  88. items_.erase(key);
  89. }
  90. private:
  91. std::map<K, T> items_;
  92. };
  93. int main() {
  94. std::string const js = "John Smith";
  95. dictionary<std::string, int> ages;
  96. assert(!ages.has(js));
  97. ages.put(js, 23);
  98. assert(ages.value_for(js) == 23);
  99. ages.remove(js);
  100. assert(ages.count() == 0);
  101. return 0;
  102. }
  103. //]