Professional C__ - Marc Gregoire [309]
hashmap const Compare& comp, const Hash& hash) throw(invalid_argument) : mSize(0), mComp(comp), mHash(hash) { if (mHash.numBuckets() <= 0) { throw invalid_argument("Number of buckets must be positive"); } mElems = new vector insert(il.begin(), il.end()); } Code snippet from Hashmap\FinalHashmap\hashmap.cpp With this initializer list constructor, a hashmap can be constructed in the following way: hashmap {"KeyOne", 100}, {"KeyTwo", 200}, {"KeyThree", 300}}; This is much nicer than using insert() and make_pair() calls: myHash.insert(make_pair("KeyOne", 100)); myHash.insert(make_pair("KeyTwo", 200)); myHash.insert(make_pair("KeyThree", 300)); hashmap Initializer List Assignment Operator In C++11, assignment operators can also accept an initializer list on the right-hand side. Following is an implementation of an initializer list assignment operator for the hashmap. It deletes all the elements from the hashmap and then delegates the work to the insert() method accepting an iterator range: template hashmap initializer_list { clear(); insert(il.begin(), il.end()); return *this; } Code snippet from Hashmap\FinalHashmap\hashmap.cpp With this assignment operator, you can write code as follows: myHash = { {"KeyOne", 100}, {"KeyTwo", 200}, {"KeyThree", 300}}; hashmap Insertion Operations In the basic hashmap section earlier in this chapter, a simple insert() method was given. In this version, four insert() versions are provided with additional features: The simple insert() operation returns a pair The version of insert() that takes a position is useless for a hashmap, but it is provided for symmetry with other kinds of collections. The position is ignored, and it merely calls the first version. The third form of insert() is a method template, so it can be used by algorithms that work on arbitrary containers. The last form of insert() accepts an initializer_list The first two insert() methods are implemented as follows: template pair hashmap { size_t bucket; // Try to find the element. auto it = findElement(x.first, bucket); if (it != (*mElems)[bucket].end()) { // The element already exists. // Convert the list iterator into a HashIterator, which // also requires the bucket and a pointer to the hashmap. HashIterator // Some compilers don't like make_pair here. pair return p; } else { // We didn't find the element, so insert a new one. mSize++; auto endIt = (*mElems)[bucket].insert((*mElems)[bucket].end(), x); pair HashIterator return p; } } template typename hashmap hashmap { // Completely ignore position return insert(x).first; } Code snippet from Hashmap\FinalHashmap\hashmap.cpp The third form of insert() is a method template for the same reason as the constructor shown earlier: It should be able to insert elements by using iterators from containers of any type. The actual implementation uses an insert_iterator, which is described earlier in this chapter: template template