// Copyright (C) 2008-2018 Lorenzo Caminiti // Distributed under the Boost Software License, Version 1.0 (see accompanying // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html //[mitchell02_dictionary #include #include #include #include template class dictionary { friend class boost::contract::access; void invariant() const { BOOST_CONTRACT_ASSERT(count() >= 0); // Non-negative count. } public: /* Creation */ // Create empty dictionary. dictionary() { boost::contract::check c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(count() == 0); // Empty. }) ; } // Destroy dictionary. virtual ~dictionary() { // Check invariants. boost::contract::check c = boost::contract::destructor(this); } /* Basic Queries */ // Number of key entries. int count() const { // Check invariants. boost::contract::check c = boost::contract::public_function(this); return items_.size(); } // Has entry for key? bool has(K const& key) const { bool result; boost::contract::check c = boost::contract::public_function(this) .postcondition([&] { // Empty has no key. if(count() == 0) BOOST_CONTRACT_ASSERT(!result); }) ; return result = (items_.find(key) != items_.end()); } // Value for a given key. T const& value_for(K const& key) const { boost::contract::check c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(has(key)); // Has key. }) ; // Find != end because of precondition (no defensive programming). return items_.find(key)->second; } /* Commands */ // Add value of a given key. void put(K const& key, T const& value) { boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); boost::contract::check c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(!has(key)); // Has not key already. }) .postcondition([&] { BOOST_CONTRACT_ASSERT(count() == *old_count + 1); // Count inc. BOOST_CONTRACT_ASSERT(has(key)); // Has key. // Value set for key. BOOST_CONTRACT_ASSERT(value_for(key) == value); }) ; items_.insert(std::make_pair(key, value)); } // Remove value for given key. void remove(K const& key) { boost::contract::old_ptr old_count = BOOST_CONTRACT_OLDOF(count()); boost::contract::check c = boost::contract::public_function(this) .precondition([&] { BOOST_CONTRACT_ASSERT(has(key)); // Has key. }) .postcondition([&] { BOOST_CONTRACT_ASSERT(count() == *old_count - 1); // Count dec. BOOST_CONTRACT_ASSERT(!has(key)); // Has not key. }) ; items_.erase(key); } private: std::map items_; }; int main() { std::string const js = "John Smith"; dictionary ages; assert(!ages.has(js)); ages.put(js, 23); assert(ages.value_for(js) == 23); ages.remove(js); assert(ages.count() == 0); return 0; } //]