c++ assignment13
chpt 13/assg-13.cpp
chpt 13/assg-13.cpp
/**
*
@author
Susant Gauchan
*
@cwid
50228244
*
@class
COSC 2336, Spring 2019
*
@ide
Visual Studio Community 2017
*
@date
May 4, 2019
*
@assg
Assignment 13
*
*
@description
Assignment 13 Dictionaries and Hash table
* implementations.
*
@note
: Please compile this file only as other files are automatically included e.g. g++ -o main assg-13.cpp
*/
#include
<
cassert
>
#include
<
iostream
>
#include
"KeyValuePair.hpp"
#include
"Employee.hpp"
#include
"HashDictionary.hpp"
using
namespace
std
;
/** main
* The main entry point for this program. Execution of this program
* will begin with this main function.
*
*
@param
argc The command line argument count which is the number of
* command line arguments provided by user when they started
* the program.
*
@param
argv The command line arguments, an array of character
* arrays.
*
*
@returns
An int value indicating program exit status. Usually 0
* is returned to indicate normal exit and a non-zero value
* is returned to indicate an error condition.
*/
int
main
(
int
argc
,
char
**
argv
)
{
// -----------------------------------------------------------------------
cout
<<
"----- testing Employee record and KeyValuePair class -----------"
<<
endl
;
KeyValuePair
<
int
,
string
>
pair
(
42
,
"blue"
);
cout
<<
"test key: "
<<
pair
.
key
()
<<
endl
;
assert
(
pair
.
key
()
==
42
);
cout
<<
"test value: "
<<
pair
.
value
()
<<
endl
;
assert
(
pair
.
value
()
==
"blue"
);
int
id
=
3
;
Employee
e
(
id
,
"Derek Harter"
,
"1234 Main Street, Commerce TX"
,
12345.67
);
cout
<<
e
<<
endl
;
assert
(
e
.
getId
()
==
3
);
assert
(
e
.
getName
()
==
"Derek Harter"
);
cout
<<
endl
;
// -----------------------------------------------------------------------
cout
<<
"-------------- testing quadratic probing -----------------------"
<<
endl
;
const
int
TABLE_SIZE
=
7
;
HashDictionary
<
int
,
Employee
>
dict
(
TABLE_SIZE
,
EMPTY_EMPLOYEE_ID
);
cout
<<
"Newly created hash dictionary should be empty, size: "
<<
dict
.
size
()
<<
endl
;
assert
(
dict
.
size
()
==
0
);
int
probeIndex
=
0
;
cout
<<
"probe index: "
<<
probeIndex
<<
" returned probe value: "
<<
dict
.
probe
(
id
,
probeIndex
)
<<
endl
;
assert
(
dict
.
probe
(
id
,
probeIndex
)
==
2
);
probeIndex
=
1
;
cout
<<
"probe index: "
<<
probeIndex
<<
" returned probe value: "
<<
dict
.
probe
(
id
,
probeIndex
)
<<
endl
;
assert
(
dict
.
probe
(
id
,
probeIndex
)
==
5
);
probeIndex
=
5
;
cout
<<
"probe index: "
<<
probeIndex
<<
" returned probe value: "
<<
dict
.
probe
(
id
,
probeIndex
)
<<
endl
;
assert
(
dict
.
probe
(
id
,
probeIndex
)
==
37
);
cout
<<
endl
;
// -----------------------------------------------------------------------
cout
<<
"-------------- testing mid-square hashing ----------------------"
<<
endl
;
// the following asserts will only work for 32 bit ints, leave asserts
// commented out if you have 64 bit asserts
cout
<<
"Assuming 32 bit (4 byte) ints for these tests: "
<<
sizeof
(
int
)
<<
endl
;
assert
(
sizeof
(
int
)
==
4
);
id
=
3918
;
cout
<<
"hash key: "
<<
id
<<
" returned hash value: "
<<
dict
.
hash
(
id
)
<<
endl
;
assert
(
dict
.
hash
(
id
)
==
1
);
id
=
48517
;
cout
<<
"hash key: "
<<
id
<<
" returned hash value: "
<<
dict
.
hash
(
id
)
<<
endl
;
assert
(
dict
.
hash
(
id
)
==
6
);
id
=
913478
;
cout
<<
"hash key: "
<<
id
<<
" returned hash value: "
<<
dict
.
hash
(
id
)
<<
endl
;
assert
(
dict
.
hash
(
id
)
==
5
);
id
=
8372915
;
cout
<<
"hash key: "
<<
id
<<
" returned hash value: "
<<
dict
.
hash
(
id
)
<<
endl
;
assert
(
dict
.
hash
(
id
)
==
4
);
// test that the distribution of the hash values
// over the possible slots/buckets looks relatively
// evenly distributed
int
counts
[
TABLE_SIZE
]
=
{
0
};
for
(
id
=
0
;
id
<
1000000
;
id
++
)
{
int
hash
=
dict
.
hash
(
id
);
counts
[
hash
]
++
;
}
// display results
int
sum
=
0
;
for
(
int
slot
=
0
;
slot
<
TABLE_SIZE
;
slot
++
)
{
cout
<<
"counts for slot["
<<
slot
<<
"] = "
<<
counts
[
slot
]
<<
endl
;
sum
=
sum
+
counts
[
slot
];
}
// spot check results
assert
(
sum
==
1000000
);
assert
(
counts
[
0
]
==
143055
);
assert
(
counts
[
6
]
==
142520
);
cout
<<
endl
;
// -----------------------------------------------------------------------
cout
<<
"-------------- testing dictionary insertion --------------------"
<<
endl
;
id
=
438901234
;
dict
.
insert
(
id
,
Employee
(
id
,
"Derek Harter"
,
"123 Main St. Commerce TX"
,
58.23
));
id
=
192834192
;
dict
.
insert
(
id
,
Employee
(
id
,
"Alice White"
,
"384 Bois'darc. Campbell TX"
,
45.45
));
id
=
998439281
;
dict
.
insert
(
id
,
Employee
(
id
,
"Bob Green"
,
"92 Washington Apt. 5 Greenville TX"
,
16.00
));
id
=
362817371
;
dict
.
insert
(
id
,
Employee
(
id
,
"Carol Black"
,
"8913 FM 24 Cooper TX"
,
28.50
));
cout
<<
"After inserting "
<<
dict
.
size
()
<<
" employees:"
<<
endl
;
cout
<<
dict
<<
endl
;
// spot check that hash table entries were correctly performed
assert
(
dict
.
size
()
==
4
);
assert
(
dict
[
3
].
key
()
==
192834192
);
assert
(
dict
[
3
].
value
().
getName
()
==
"Alice White"
);
assert
(
dict
[
1
].
key
()
==
438901234
);
assert
(
dict
[
1
].
value
().
getName
()
==
"Derek Harter"
);
cout
<<
endl
;
// -----------------------------------------------------------------------
cout
<<
"-------------- testing dictionary search -----------------------"
<<
endl
;
id
=
438901234
;
e
=
dict
.
find
(
id
);
cout
<<
"Search for id: "
<<
id
<<
endl
;
cout
<<
" Found employee: "
<<
e
<<
endl
;
assert
(
e
.
getId
()
==
id
);
assert
(
e
.
getName
()
==
"Derek Harter"
);
id
=
362817371
;
e
=
dict
.
find
(
id
);
cout
<<
"Search for id: "
<<
id
<<
endl
;
cout
<<
" Found employee: "
<<
e
<<
endl
;
assert
(
e
.
getId
()
==
id
);
assert
(
e
.
getName
()
==
"Carol Black"
);
id
=
239481432
;
e
=
dict
.
find
(
id
);
cout
<<
"Unsuccessful Search for id: "
<<
id
<<
endl
;
cout
<<
" Found employee: "
<<
e
<<
endl
;
assert
(
e
.
getId
()
==
EMPTY_EMPLOYEE_ID
);
assert
(
e
.
getName
()
==
""
);
cout
<<
endl
;
// return 0 to indicate successful completion
return
0
;
}
chpt 13/Employee.cpp
chpt 13/Employee.cpp
/**
*
@author
Susant Gauchan
*
@cwid
50228244
*
@class
COSC 2336, Spring 2019
*
@ide
Visual Studio Community 2017
*
@date
May 4, 2019
*
@assg
Assignment 13
*
*
@description
Simple example of an Employee record/class
* we can use to demonstrate HashDictionary key/value pair
* management.
*/
#include
<
string
>
#include
<
iostream
>
#include
<
iomanip
>
#include
<
sstream
>
#include
"Employee.hpp"
using
namespace
std
;
/** constructor
* Default constructor for our Employee record/class. Construct an
* empty employee record
*/
Employee
::
Employee
()
{
this
->
id
=
EMPTY_EMPLOYEE_ID
;
this
->
name
=
""
;
this
->
address
=
""
;
this
->
salary
=
0.0
;
}
/** constructor
* Basic constructor for our Employee record/class.
*/
Employee
::
Employee
(
int
id
,
string name
,
string address
,
float
salary
)
{
this
->
id
=
id
;
this
->
name
=
name
;
this
->
address
=
address
;
this
->
salary
=
salary
;
}
/** id accessor
* Accessor method to get the employee id.
*
*
@returns
int Returns the integer employee id value.
*/
int
Employee
::
getId
()
const
{
return
id
;
}
/** name accessor
* Accessor method to get the employee name.
*
*
@returns
string Returns the string containing the full
* employee name for this record.
*/
string
Employee
::
getName
()
const
{
return
name
;
}
/** overload operator<<
* Friend function to ouput representation of Employee to an
* output stream.
*
*
@param
out A reference to an output stream to which we should
* send the representation of an employee record for display.
*
@param
employee The reference to the employee record to be displayed.
*
*
@returns
ostream& Returns a reference to the original output
* stream, but now the employee information should have been
* inserted into the stream for display.
*/
ostream
&
operator
<<
(
ostream
&
out
,
Employee
&
employee
)
{
//out << "Employee id: " << employee.id << endl
// << " name : " << employee.name << endl
// << " address: " << employee.address << endl
// << " salary : " << fixed << setprecision(2) << employee.salary << endl;
out
<<
"( id: "
<<
employee
.
id
<<
", "
<<
employee
.
name
<<
", "
<<
employee
.
address
<<
", "
<<
fixed
<<
setprecision
(
2
)
<<
employee
.
salary
<<
" )"
<<
endl
;
return
out
;
}
chpt 13/Employee.hpp
/** * @author Susant Gauchan * @cwid 50228244 * @class COSC 2336, Spring 2019 * @ide Visual Studio Community 2017 * @date May 4, 2019 * @assg Assignment 13 * * @description Simple example of an Employee record/class * we can use to demonstrate HashDictionary key/value pair * management. */ #include <string> #include <iostream> using namespace std; #ifndef EMPLOYEE_HPP #define EMPLOYEE_HPP // This should really be a class constant, however this // global constant represents a flag that is used to // indicate empty slots and/or failed search. const int EMPTY_EMPLOYEE_ID = 0; /** Employee * A simple Employee class/record to demonstrate/test * our hashing dictionary assignment. * NOTE: we are using 0 as a flag to represent an unused * slot or an invalid/empty employee. This is used/assumed * by our dictionary class to determine if a slot is empty * and/or to give a failure result for a failed search. */ class Employee { private: int id; string name; string address; float salary; public: Employee(); Employee(int id, string name, string address, float salary); int getId() const; string getName() const; friend ostream& operator<<(ostream& out, Employee& employee); }; #include "Employee.cpp" #endif // EMPLOYEE_HPP
chpt 13/HashDictionary.cpp
chpt 13/HashDictionary.cpp
/**
*
@author
Susant Gauchan
*
@cwid
50228244
*
@class
COSC 2336, Spring 2019
*
@ide
Visual Studio Community 2017
*
@date
May 4, 2019
*
@assg
Assignment 13
*
*
@description
Template class for definining a dictionary
* that uses a hash table of KeyValuePair items.
* Based on Shaffer hashdict implementation pg. 340
*/
#include
<
string
>
#include
<
iostream
>
#include
<
iomanip
>
#include
<
sstream
>
#include
"HashDictionary.hpp"
#include
"math.h"
using
namespace
std
;
/** constructor
* Standard constructor for the HashDictionary
*
*
@param
tableSize The size of the hash table that should be
* generated for internal use by this dictionary for hasing.
*
@param
emptyKey A special flag/value that can be used to detect
* invalid/unused keys. We need this so we can indicate which
* slots/buckets in our hash table are currently empty, and also
* this value is used as a rnity 2017
*
@date
April 8, 2019
*
@assg
Assignment 13
*
*
@description
Template class for definining a dictionary
* that uses a hash table of KeyValuePair items.
* Based on Shaffer hashdict implementation pg. 340
*/
/** constructor
* Standard constructor for the HashDictionary
*
*
@param
tableSize The size of the hash table that should be
* generated for internal use by this dictionary for hasing.
*
@param
emptyKey A special flag/value that can be used to detect
* invalid/unused keys. We need this so we can indicate which
* slots/buckets in our hash table are currently empty, and also
* this value is used as a return result when an unsuccessful
* search is performed on the dictionary.
*/
template
<
class
Key
,
class
Value
>
HashDictionary
<
Key
,
Value
>::
HashDictionary
(
int
tableSize
,
Key
emptyKey
)
{
this
->
tableSize
=
tableSize
;
this
->
EMPTYKEY
=
emptyKey
;
valueCount
=
0
;
// allocate an array/table of the indicated initial size
hashTable
=
new
KeyValuePair
<
Key
,
Value
>
[
tableSize
];
// initialize the hash table so all slots are initially empty
for
(
int
index
=
0
;
index
<
tableSize
;
index
++
)
{
hashTable
[
index
].
setKey
(
EMPTYKEY
);
}
}
/** destructor
* Standard destructor for the HashDictionary. Be good memory managers and
* free up the dynamically allocated array of memory pointed to by hashTable.
*/
template
<
class
Key
,
class
Value
>
HashDictionary
<
Key
,
Value
>::~
HashDictionary
()
{
delete
[]
hashTable
;
}
/** size
* Accessor method to get the current size of this dictionary,
* e.g. the count of the number of key/value pairs currently being
* managed in our hash table.
*
*
@returns
in Returns the current number of items being managed by
* this dictionary and currently in our hashTable.
*/
template
<
class
Key
,
class
Value
>
int
HashDictionary
<
Key
,
Value
>::
size
()
const
{
return
valueCount
;
}
// Place your implementations of the class methods probe(), hash(),
// insert() and find() here
/**
* probe
* Probe method to define the probed sequence for closed hashing
*
*
@params
Key the key value used whenly when secondary hashing is used
*
*
@params
index The index at which collision is occured
*
*
@returns
integer which is the required offset to be added to the
* previous index
*
*/
template
<
class
Key
,
class
Value
>
int
HashDictionary
<
Key
,
Value
>::
probe
(
Key
,
int
index
)
const
{
return
1
*
index
*
index
+
2
*
index
+
2
;
}
/**
* hash
* function to calculate hash of the given key value using mid square
* hashing function
*
*
@params
x the key value of which hash is to be calculated
*
*
*
@returns
integer The result of hash function i.e. hash of given key
*
*/
template
<
class
Key
,
class
Value
>
int
HashDictionary
<
Key
,
Value
>::
hash
(
Key
x
)
{
if
(
x
==
192834192
)
{
cout
<<
"square "
<<
x
*
x
<<
endl
;
// this prints 1914409216 which is clearly
// not the square of 192834192
}
x
=
x
*
x
;
if
(
sizeof
(
int
)
==
4
)
{
x
=
x
&
0x00FFFFFF
;
x
=
x
>>
8
;
}
else
if
(
sizeof
(
int
)
==
8
)
{
x
=
x
&
0x0000FFFFFFFF0000
;
}
return
x
%
tableSize
;
}
/**
* insert
* function to insert key value pair to our hashtable
*
*
@params
k the key of the key value pair to be inserted
*
*
@params
v Value of the key value pair to be inserted
*
*/
template
<
class
Key
,
class
Value
>
void
HashDictionary
<
Key
,
Value
>::
insert
(
const
Key
&
k
,
const
Value
&
v
)
{
int
home
;
int
pos
=
home
=
(
hash
(
k
)
+
probe
(
k
,
0
))
%
tableSize
;
for
(
int
i
=
0
;
EMPTYKEY
!=
(
hashTable
[
pos
]).
key
();
i
++
)
{
pos
=
(
home
+
probe
(
k
,
i
))
%
tableSize
;
cout
<<
"POS: "
<<
pos
<<
endl
;
}
KeyValuePair
<
Key
,
Value
>
temp
(
k
,
v
);
hashTable
[
pos
]
=
temp
;
valueCount
+=
1
;
}
/**
* hash
* function to search and find the value of the keyvalue pair by given Key
* from the hashtable
*
*
@params
x the key value of which value is to be found
*
*
*
@returns
Value The value stored in that key
*
*/
template
<
class
Key
,
class
Value
>
Value
HashDictionary
<
Key
,
Value
>::
find
(
const
Key
&
k
)
{
int
home
;
// Home position for k
int
pos
=
home
=
(
hash
(
k
)
+
probe
(
k
,
0
))
%
tableSize
;
// Initial position is home slot
for
(
int
i
=
0
;
(
k
!=
(
hashTable
[
pos
]).
key
())
&&
(
EMPTYKEY
!=
(
hashTable
[
pos
]).
key
());
i
++
)
pos
=
(
home
+
probe
(
k
,
i
))
%
tableSize
;
// Next on probe sequence
if
(
k
==
(
hashTable
[
pos
]).
key
())
// Found it
return
(
hashTable
[
pos
]).
value
();
else
return
Value
();
}
/** overload indexing operator[]
* Overload indexing operator[] to provide direct access
* to hash table. This is not normally part of the Dictionary
* API/abstraction, but included here for testing.
*
*
@param
index An integer index. The index should be in the range 0 - tablesize-1.
*
*
@returns
KeyValuePair<> Returns a KeyValuePair object if the index into the
* internal hash table is a valid index. This method throws an exception if
* the index is not a valid slot of the hash table.
*/
template
<
class
Key
,
class
Value
>
KeyValuePair
<
Key
,
Value
>
&
HashDictionary
<
Key
,
Value
>::
operator
[](
int
index
)
{
if
(
index
<
0
||
index
>=
tableSize
)
{
cout
<<
"Error: <HashDictionary::operator[] invalid index: "
<<
index
<<
" table size is currently: "
<<
tableSize
<<
endl
;
assert
(
false
);
}
return
hashTable
[
index
];
}
/** HashDictionary output stream operator
* Friend function for HashDictionary. We normally wouldn't have
* something like this for a Dictionary or HashTable, but for testing
* and learning purposes, we want to be able to display the contents of
* each slot in the hash table of a HashDictionary container.
*
*
@param
out An output stream reference into which we should insert
* a representation of the given HashDictionary.
*
@param
aDict A HashDictionary object that we want to display/represent
* on an output stream.
*
*
@returns
ostream& Returns a reference to the original given output stream,
* but now the values representing the dictionary we were given should
* have been sent into the output stream.
*/
template
<
typename
K
,
typename
V
>
ostream
&
operator
<<
(
ostream
&
out
,
const
HashDictionary
<
K
,
V
>
&
aDict
)
{
for
(
int
slot
=
0
;
slot
<
aDict
.
tableSize
;
slot
++
)
{
out
<<
"Slot: "
<<
slot
<<
endl
;
out
<<
" Key : "
<<
aDict
.
hashTable
[
slot
].
key
()
<<
endl
;
out
<<
" Value: "
<<
aDict
.
hashTable
[
slot
].
value
()
<<
endl
;
}
out
<<
endl
;
return
out
;
}
chpt 13/HashDictionary.hpp
/** * @author Susant Gauchan * @cwid 50228244 * @class COSC 2336, Spring 2019 * @ide Visual Studio Community 2017 * @date May 4, 2019 * @assg Assignment 13 * * @description Template class for definining a dictionary * that uses a hash table of KeyValuePair items. * Based on Shaffer hashdict implementation pg. 340 */ #include <cassert> #include <iostream> #include "KeyValuePair.hpp" using namespace std; #ifndef HASHDICTIONARY_HPP #define HASHDICTIONARY_HPP /** HashDictionary * An implementation of a dictionary that uses a hash table to insert, search * and delete a set of KeyValuePair items. In the assignment, we will be * implementing a closed hashing table with quadratic probing. The hash function * will implement a version of the mid-square hasing function described in * our Shaffer textbook. * * @value hashTable An array of KeyValuePair items, the hash table this class/container * is managing. * @value tableSize The actual size of the hashTable array * @value valueCount The number of KeyValuePair items that are currently being * managed and are contained in the hashTable * @value EMPTYKEY A special user-supplied key that can be used to indicate empty * slots. Since how we determine what is a valid/invalid key will depend on the * key type, the user must supply this special flag/value when setting up the * hash dictionary. */ template <class Key, class Value> class HashDictionary { protected: KeyValuePair<Key, Value>* hashTable; // the hash table int tableSize; // the size of the hash table, e.g. symbol M from textbook int valueCount; // the count of the number of value items currently in table Key EMPTYKEY; // a special user-supplied key that can be used to indicate empty slots public: // constructors and destructors HashDictionary(int tableSize, Key emptyKey); ~HashDictionary(); // accessor methods int size() const; // searching and insertion // all 4 of the methods you were required to create for this // assignment should have appropriate class method signatures // defined here. int probe(Key,int index) const; int hash(Key); void insert(const Key &k,const Value &v); Value find(const Key &k); // overload operators (mostly for testing) KeyValuePair<Key, Value>& operator[](int index); template <typename K, typename V> friend ostream& operator<<(ostream& out, const HashDictionary<K, V>& aDict); }; #include "HashDictionary.cpp" #endif // HASHDICTIONARY_HPP
chpt 13/KeyValuePair.cpp
chpt 13/KeyValuePair.cpp
/**
*
@author
Susant Gauchan
*
@cwid
50228244
*
@class
COSC 2336, Spring 2019
*
@ide
Visual Studio Community 2017
*
@date
May 4, 2019
*
@assg
Assignment 13
*
*
@description
Template class for definining Key/Value pairs,
* suitable for dictionary and hash table implementations.
* Based on Shaffer KVPair ADT definition, pg. 139 Fig 4.31.
*/
#include
<
string
>
#include
<
iostream
>
#include
<
iomanip
>
#include
<
sstream
>
#include
"KeyValuePair.hpp"
using
namespace
std
;
/** constructor
* Default constructor for a KeyValuePair.
*/
template
<
class
Key
,
class
Value
>
KeyValuePair
<
Key
,
Value
>::
KeyValuePair
()
{
}
/** constructor
* Standard constructor for a KeyValuePair.
*
*
@param
key The key portion that is to be stored in this pair.
*
@param
value The value portion that is to be stored in this pair.
*/
template
<
class
Key
,
class
Value
>
KeyValuePair
<
Key
,
Value
>::
KeyValuePair
(
Key
key
,
Value
value
)
{
this
->
myKey
=
key
;
this
->
myValue
=
value
;
}
/** key accessor
* Accessor method to get and return the key for this key/value pair
*
*
@returns
Key Returns an object of template type Key, which is the
* key portion of the pair in this container.
*/
template
<
class
Key
,
class
Value
>
Key
KeyValuePair
<
Key
,
Value
>::
key
()
{
return
myKey
;
}
/** key setter
* Accessor method to set the key for this key/value pair
*
*
@param
key The new value to update the key to for this pair.
*/
template
<
class
Key
,
class
Value
>
void
KeyValuePair
<
Key
,
Value
>::
setKey
(
Key
key
)
{
this
->
myKey
=
key
;
}
/** value accessor
* Accessor method to get and return the value for this key/value pair.
*
*
@returns
Value& Returns a reference to the value object in this
* key value pair container.
*/
template
<
class
Key
,
class
Value
>
Value
&
KeyValuePair
<
Key
,
Value
>::
value
()
{
return
myValue
;
}
chpt 13/KeyValuePair.hpp
/** * @author Susant Gauchan * @cwid 50228244 * @class COSC 2336, Spring 2019 * @ide Visual Studio Community 2017 * @date May 4, 2019 * @assg Assignment 13 * * @description Template class for definining Key/Value pairs, * suitable for dictionary and hash table implementations. * Based on Shaffer KVPair ADT definition, pg. 139 Fig 4.31. */ #ifndef KEYVALUEPAIR_HPP #define KEYVALUEPAIR_HPP /** KeyValue Pair * Definition of basic key/value pair container. This container of course * associates a value (usually a record like a class or struct), with * a key (can be anything). * * We do not use the comparator Strategy pattern as discussed in * Shaffer pg. 144 here. We assume that the Key type has suitably * overloaded operators for <, >, ==, <=, >= operations as needed * in order to compare and order keys if needed by dictionaries and * hash tables using a KeyValuePair. * * @value key The key for a key/value pair item/association. * @value value The value for a key/value pair, usually something like * a record (a class or struct of data we are hashing or keeping in * a dictionary). */ template <class Key, class Value> class KeyValuePair { private: Key myKey; Value myValue; public: // constructors KeyValuePair(); KeyValuePair(Key key, Value value); // accessors, getters and setters Key key(); void setKey(Key key); Value& value(); }; #include "KeyValuePair.cpp" #endif // KEYVALUEPAIR_HPP