Professional C__ - Marc Gregoire [213]
using std::multimap;
using std::string;
using std::list;
class BuddyList
{
public:
BuddyList();
// Adds buddy as a friend of name
void addBuddy(const string& name, const string& buddy);
// Removes buddy as a friend of name
void removeBuddy(const string& name, const string& buddy);
// Returns true if buddy is a friend of name, false otherwise.
bool isBuddy(const string& name, const string& buddy) const;
// Retrieves a list of all the friends of name
list protected: multimap }; Code snippet from BuddyList\BuddyList.h Here is the implementation, with comments explaining the code. It demonstrates the use of lower_bound(), upper_bound(), and equal_range(): void BuddyList::addBuddy(const string& name, const string& buddy) { // Make sure this buddy isn't already there. We don't want // to insert an identical copy of the key/value pair. if (!isBuddy(name, buddy)) { mBuddies.insert({name, buddy});// Using C++11 initializer_list } } void BuddyList::removeBuddy(const string& name, const string& buddy) { // Obtain the beginning and end of the range of elements with // key 'name'. auto start = mBuddies.lower_bound(name); auto end = mBuddies.upper_bound(name); // Iterate through the elements with key 'name' looking // for a value 'buddy' for (; start != end; ++start) { if (start->second == buddy) { // We found a match! Remove it from the map. mBuddies.erase(start); break; } } } bool BuddyList::isBuddy(const string& name, const string& buddy) const { // Obtain the beginning and end of the range of elements with // key 'name'. auto start = mBuddies.lower_bound(name); auto end = mBuddies.upper_bound(name); // Iterate through the elements with key 'name' looking // for a value 'buddy'. If there are no elements with key 'name', // start equals end, so the loop body doesn't execute. for (; start != end; ++start) { if (start->second == buddy) { // We found a match! return true; } } // No matches return false; } list { // Obtain the pair of iterators marking the range containing // elements with key 'name'. auto its = mBuddies.equal_range(name); // Create a list with all names in the range (all buddies of name). list for (; its.first != its.second; ++its.first) { buddies.push_back(its.first->second); } return buddies; } Code snippet from BuddyList\BuddyList.cpp Note that removeBuddy() can’t simply use the version of erase() that erases all elements with a given key, because it should erase only one element with the key, not all of them. Note also that getBuddies() can’t use insert() on the list to insert the elements in the range returned by equal_range(), because the elements referred to by the multimap iterators are key/value pairs, not strings. The getBuddies() method must iterate explicitly through the list extracting the string from each key/value pair and pushing it onto the new list to be returned. Here is a simple test of the BuddyList: BuddyList buddies; buddies.addBuddy("Harry Potter", "Ron Weasley"); buddies.addBuddy("Harry Potter", "Hermione Granger"); buddies.addBuddy("Harry Potter", "Hagrid"); buddies.addBuddy("Harry Potter", "Draco Malfoy"); // That's not right! Remove Draco. buddies.removeBuddy("Harry Potter", "Draco Malfoy"); buddies.addBuddy("Hagrid", "Harry Potter"); buddies.addBuddy("Hagrid", "Ron Weasley"); buddies.addBuddy("Hagrid", "Hermione Granger"); auto harryBuds = buddies.getBuddies("Harry Potter"); cout << "Harry's friends: " << endl; for (auto& name : harryBuds) { cout << "\t" << name << endl; } Code snippet from BuddyList\BuddyListTest.cpp The output should be as follows: Harry's friends: