There is nothing circular about this! The Partial_Map entries (buckets) in the array (hash-table) simply have a different implementation than the one you are writing code for here. In the default template parameters of the code skeleton you are given for Partial_Map_Kernel_6, each of the buckets defaults to being a Partial_Map_Kernel_1 object. Yet a client of your code could decide to use some other implementation of Partial_Map_Kernel for the buckets -- say, Partial_Map_Kernel_7, which you will not implement until the next lab assignment. This helps illustrate one of the huge advantages of abstract contracts and decoupling concrete components using templates: your code can be made general enough that it will still be usable without modification with future code that hasn't even been thought of yet!
The other interesting thing to note about this lab is how little code you have to write for the bodies of the Partial_Map_Kernel_6 operations. Hashing, in other words, offers a tremendous performance improvement for very little code. On the other hand, as in all kernel implementations, you have to get this code all correct, for if even one of the operation bodies is wrong then other operations might appear not to work correctly during testing. This makes debugging a challenge. There are two reasons for this. First, the test driver uses a checking component for Partial_Map_Kernel in order to prevent you from executing a buggy test script. This checking component calls your own code to do the checking. So, for example, the first time you Define something in your test script, the checking component starts by asking whether the D_Item value is already defined in the Partial_Map object; and this means that, if your code for Is_Defined doesn't work correctly, you might get a violated assertion while appearing to test Define. (This happens to someone every quarter!) Second, if your code for any operation fails to make the representation invariant true at the time it returns, then the next operation called in the test script might break; but the problem is actually with the previous operation. Make sure you understand both of these difficulties so you can avoid them.
cp -R /class/sce/now/222/labs/lab03/Lab03/ .
cd Lab03
submit c222?? lab3 CT/Partial_Map/Kernel_6.hIf you get an error message rather than a confirmation of success, please read the message; it contains useful information! Do not just run the same command again. Save the e-mail you get as a receipt of submission, just in case.
The Initialize operation is a new one. Its purpose is to construct the representation for an initial value of a Partial_Map object (which is an empty set). Initialize is an operation that you never call explicitly; all calls to it are inserted automatically by the C++ compiler at the appropriate places. But for this case, unlike previous examples of kernel implementations, you do have to write a body for it. The reason is that before Initialize executes, C++ has automatically initialized, to their respective initial values, the fields of the Representation record. If automatic initialization of these fields happens to result in the representation of an initial value of the type being implemented then you don't need to write any code for Initialize. That has been the situation in the previous implementation examples you've done. But here, the representation of an empty Partial_Map_Kernel_6 object must have the bounds of the Array field (called hash_table) set to 0 and hash_table_size-1, respectively; by default they are initially 1 and 0. Therefore, you need to put (only) the following code into the body of Initialize:
self[hash_table].Set_Bounds (0, hash_table_size-1);