I seem to be having some templating issues with my HashMap functions. I need to run a <string, vector<string>> hash map in the end. And it's giving a lot of issues.
I need to be able to be able to push items on the vector. I was using the [] operator.
test
using namespace std;
#include "MyHashMap.hpp"
#include <vector>
int main()
{
MyHashMap <string, vector <string> > test (10);
test["x"].push_back("Y");
}
ERRORS (There are a lot of them. I think they are related so I will only show 1)
In member function ‘valueType& MyHashMap::operator [with keyType = std::basic_string, std::allocator >, valueType = std::vector, std::allocator >, std::allocator, std::allocator > > >]’:
test.cpp:13: instantiated from here
MyHashMap.hpp:52: error: cannot convert ‘MyHashMap, std::allocator >, std::vector, std::allocator >, std::allocator, std::allocator > > > >::EntryType’ to ‘EntryType’ in assignment
MyHashMap.hpp: In member function ‘int MyHashMap::findPos(keyType&) [with keyType = std::basic_string, std::allocator >, valueType = std::vector, std::allocator >, std::allocator, std::allocator > > >]’:
MyHashMap.hpp:46: instantiated from ‘valueType& MyHashMap::operator [with keyType = std::basic_string, std::allocator >, valueType = std::vector, std::allocator >, std::allocator, std::allocator > > >]’
MyHashMap.hpp
#include <string>
#include "HashEntry.hpp"
using namespace std;
template <typename keyType, typename valueType>
class MyHashMap
{
public:
/***********************************************
explicit HashTable( int size = 1009 ) : array(size)
CONSTRUCTOR with default size of 1009
***********************************************/
explicit MyHashMap(int size=1000):tableSize(size)
{
array = new HashEntry <keyType, valueType> [tableSize];
}
int size()
{
return tableSize;
}
/***********************************************
***********************************************/
valueType& operator[](keyType x )
{
// Insert x as active
int currentPos = findPos( x );
if( isActive( currentPos ) )
{
return array[currentPos].value;
}
array[ currentPos ].key = x;
array[ currentPos ].info = ACTIVE;
return array[currentPos].value;
}
/***********************************************
Returns pointer to HashEntry if it is active
Returns NULL otherwise
***********************************************/
HashEntry<keyType,valueType>& getPos(int n)
{
if(isActive(n))
{
return array[n];
}
}
/***********************************************
bool insert( keyType & x, & valueType y)
inserts x and y into hashMap
***********************************************/
bool insert( keyType & x, valueType& y)
{
// Insert x as active
//currentPos gets position to try to insert
int currentPos = findPos( x );
if( isActive( currentPos ) )
{
return false;
}
array[ currentPos ].key = x;
array[ currentPos ].value = y;
return true;
}
/***********************************************
LAZY DELETION
***********************************************/
bool remove( keyType x )
{
int currentPos = findPos( x );
if( !isActive( currentPos ) )
return false;
array[ currentPos ].info = DELETED;
return true;
}
/***********************************************
***********************************************/
valueType* find( keyType & x )
{
//currentPos gets position where Search for x terminates
int currentPos = findPos(x);
if(isActive(currentPos))
return array[currentPos].value;
else
return NULL;
}
enum EntryType { ACTIVE, EMPTY, DELETED };
private:
HashEntry <keyType, valueType>* array;
int tableSize;
/***********************************************
***********************************************/
bool isActive( int currentPos )
{
return array[ currentPos ].info == ACTIVE;
}
/***********************************************
int findPos( HashedObj & x )
Returns the position where the search for x terminates
***********************************************/
int findPos( keyType & x )
{
int offset = 1;
int currentPos = myhash( x );
// Assuming table is half-empty, and table length is prime,
// this loop terminates
while( array[ currentPos ].info != EMPTY &&
array[ currentPos ].element != x )
{
currentPos += offset; // Compute ith probe
offset += 2;
if( currentPos >= tableSize )
currentPos -= tableSize;
}
return currentPos;
}
/***********************************************
Hash function for string
***********************************************/
int myhash( string & x )
{
int hashVal = 0;
for(int i = 0; i < x.length(); i++)
{
hashVal = 37*hashVal+x[i];
}
hashVal %= tableSize;
if(hashVal < 0)
hashVal += tableSize;
return hashVal;
}
};
#endif
Hash Entry
using namespace std;
enum EntryType { ACTIVE, EMPTY, DELETED };
template <typename keyType, typename valueType>
struct HashEntry
{
keyType key;
valueType value;
EntryType info;
/***********************************************
HashEntry CONSTRUCTOR
***********************************************/
HashEntry(keyType x = keyType(), valueType y = valueType(),
EntryType i = EMPTY ):key(x), value(y),info( i ) { }
};
#endif
The declaration of your member MyHashMap::array is wrong. Change it to:
HashEntry <keyType, valueType>* array;
In the constructor:
explicit MyHashMap(int size = 1000) : tableSize(size)
{
array = new HashEntry<keyType, valueType>[tableSize];
}
And it should work correctly!
Related
Currently my class looks like this, by unit tests done, it works but my goal will be to implement as precise in question the lib Boost and especially the multi index container.
I tried to change the type of the items but it didn't work, like this:
typedef multi_index_container<items,indexed_by<sequenced<>,hashed_unique<identity<Item> >>> item_list;
I got a message: Invalid use of non-static data member '_items'. This kind of error I can understand it but i not specify it because it is the global implementation that worries me
If you find any other error apart from my precise question, I am also a taker.
template<typename Tkey, typename Tval>
class CacheWeb{
private:
unsigned int capacity;
std::list<std::pair<Tkey, Tval>> items;
std::unordered_map<key, typename std::list<std::pair<Tkey, Tval>>::iterator> lookup;
CacheWeb(const CacheWeb&) = delete;
CacheWeb& operator=(const CacheWeb&) = delete;
int capacityOut(){
if( capacity == 0 || lookup.size() < capacity ) {
return 0;
}
int cnt = 0;
while(lookup.size() > capacity) {
lookup.erase(items.back().first);
items.pop_back();
++cnt;
}
return cnt;
};
public:
CacheWeb(int icapacity) : capacity(icapacity){};
virtual ~CacheWeb() = default;
int size(){
return lookup.size();
};
bool empty(){
return lookup.empty();
};
void clear(){
lookup.clear();
items.clear();
};
bool contains(const Tkey& key){
return lookup.find(key) != lookup.end();
};
void remove(const Tkey& key){
auto it = lookup.find(key);
items.erase(it->second);
lookup.erase(it);
};
void put(const Tkey& key, const Tval& val){
auto it = lookup.find(key);
if( it != lookup.end() ) {
it->second->second = val;
items.splice(items.begin(), items, it->second);
return;
}
items.emplace_front(key, val);
lookup[key] = items.begin();
capacityOut();
};
std::list<std::pair<Tkey, Tval>>getItems(){
return items;
};
const VAL_T& get(const Tkey& key){
const auto it = lookup.find(key);
if( it == lookup.end() ) {
throw std::invalid_argument("Key does not exist");
}
items.splice(items.begin(), items, it->second);
return it->second->second;
};
};
}
Something like this can do:
Live Coliru Demo
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/key.hpp>
template<typename Tkey, typename Tval>
class CacheWeb{
private:
using value_type = std::pair<Tkey, Tval>;
unsigned int capacity;
boost::multi_index_container<
value_type,
boost::multi_index::indexed_by<
boost::multi_index::sequenced<>,
boost::multi_index::hashed_unique<boost::multi_index::key<&value_type::first>>
>
> container;
CacheWeb(const CacheWeb&) = delete;
CacheWeb& operator=(const CacheWeb&) = delete;
int capacityOut(){
if( capacity == 0 || container.size() < capacity ) {
return 0;
}
int cnt = 0;
while(container.size() > capacity) {
container.pop_back();
++cnt;
}
return cnt;
};
public:
CacheWeb(int icapacity) : capacity(icapacity){};
virtual ~CacheWeb() = default;
int size(){
return container.size();
};
bool empty(){
return container.empty();
};
void clear(){
container.clear();
};
bool contains(const Tkey& key){
const auto& lookup = container.template get<1>();
return lookup.find(key) != container.template get<1>().end();
};
void remove(const Tkey& key){
container.erase(key);
};
void put(const Tkey& key, const Tval& val){
auto& lookup = container.template get<1>();
auto it = lookup.find(key);
if( it != lookup.end() ) {
lookup.modify(it,[&](value_type& x){ x.second = val; });
}
else{
it=lookup.emplace(key, val).first;
}
container.relocate(container.begin(),container.template project<0>(it));
capacityOut();
};
std::list<std::pair<Tkey, Tval>>getItems(){
return {container.begin(), container.end()};
};
const Tval& get(const Tkey& key){
const auto& lookup = container.template get<1>();
const auto it = lookup.find(key);
if( it == lookup.end() ) {
throw std::invalid_argument("Key does not exist");
}
return it->second;
}
};
#include <iostream>
int main()
{
CacheWeb<int,int> c(10);
for(int i=0;i<11;++i)c.put(i,i);
for(const auto& x:c.getItems()){
std::cout<<"("<<x.first<<","<<x.second<<")";
}
std::cout<<"\n";
for(int i=1;i<11;++i){
std::cout<<i<<"->"<<c.get(i)<<" ";
}
std::cout<<"\n";
}
Output
(10,10)(9,9)(8,8)(7,7)(6,6)(5,5)(4,4)(3,3)(2,2)(1,1)
1->1 2->2 3->3 4->4 5->5 6->6 7->7 8->8 9->9 10->10
I have to write an ArrayDictionary.cpp file that follows the ArrayDictionary.h file listed below. The purpose of the .h file is an array-based implementation of the ADT dictionary that organizes its data items in sorted search-key order. Search keys in the dictionary are unique.
The code includes ArrayDictionary.h and ArrayDictionary.cpp. The ArrayDictionary.h file also includes other .h files. Please let me know if you need them to help me.
I'm having trouble with variables that cannot be identify in the ArrayDicionary.cpp file. The variables are items and entryCount that are having errors.
//ArrayDictionary.h
#pragma once
#ifndef _ARRAY_DICTIONARY
#define _ARRAY_DICTIONARY
#include "DictionaryInterface.h"
#include "Entry.h"
#include "NotFoundException.h"
#include "PrecondViolatedExcept.h"
template < class KeyType, class ValueType>
class ArrayDictionary : public DictionaryInterface < KeyType, ValueType>
{
private:
static const int DEFAULT_CAPACITY = 21; // Small capacity to test for
// a full dictionary
Entry<KeyType, ValueType>* entries; // Array of dictionary entries
int entryCount; // Maximum capacity of the dictionary
void destroyDictionary();
int findEntryIndex(int firstIndex, int lastIndex, const KeyType & searchKey) const;
int maxEntries;
public:
ArrayDictionary();
ArrayDictionary(int maxNumberOfEntries);
ArrayDictionary(const ArrayDictionary<KeyType, ValueType>&dictionary);
virtual ~ArrayDictionary();
bool isEmpty() const;
int getNumberOfEntries() const;
bool add(const KeyType& searchKey, const ValueType& newValue) throw (PrecondViolatedExcep);
bool remove(const KeyType& searchKey);
void clear();
ValueType getValue(const KeyType& searchKey) const throw (NotFoundException);
bool contains(const KeyType& searchKey) const;
/** Traverses the items in this dictionary in sorted search-key order
and calls a given client function once for each item. */
void traverse(void visit(ValueType&)) const;
}; // end ArrayDictionary
#include "ArrayDictionary.cpp"
#endif
#include <iostream>
#include "ArrayDictionary.h"
#include "PrecondViolatedExcept.h"
template < class KeyType, class ValueType>
void ArrayDictionary<KeyType, ValueType>::destroyDictionary()
{
delete[] items;
items = new Entry[maxEntries];
entryCount = 0;
}
template < class KeyType, class ValueType>
inline int findEntryIndex(int firstIndex, int lastIndex, const KeyType& searchKey)
{
int IndexMiddle = firstIndex + (lastIndex - firstIndex) / 2;
if (firstIndex > lastIndex)
return -1;
else if (searchKey == items[IndexMiddle].getKey())
return IndexMiddle;
else if (searchKey < items[IndexMiddle].getKey())
return findEntryIndex(firstIndex, IndexMiddle - 1, searchKey);
else
return findEntryIndex(IndexMiddle + 1, lastIndex, searchKey);
}
template < class KeyType, class ValueType>
inline ArrayDictionary<KeyType, ValueType>::ArrayDictionary() : entryCount(0), maxEntries(DEFAULT_CAPACITY)
{
items = new Entry[DEFAULT_CAPACITY];
}
template < class KeyType, class ValueType>
inline ArrayDictionary<KeyType,ValueType>::ArrayDictionary(int maxNumberOfEntries) :
entryCount(0), maxEntries(maxNumberOfEntries)
{
items = new Entry[maxNumberOfEntries];
}
template < class KeyType, class ValueType>
inline ArrayDictionary<KeyType,ValueType>::ArrayDictionary(const ArrayDictionary& dictionary) :
entryCount(dictionary.itemCount), maxEntries(dictionary.maxEntries)
{
items = new Entry[dictionary.maxEntries];
for (int index = 0; index < dictionary.entryCount; index++)
{
items[index] = dictionary.items[index];
}
}
template < class KeyType, class ValueType>
inline ArrayDictionary<KeyType, ValueType>::~ArrayDictionary()
{
destroyDictionary();
}
template < class KeyType, class ValueType>
inline bool isEmpty()
{
return (entryCount == 0);
}
template < class KeyType, class ValueType>
inline int getNumberOfItems()
{
return entryCount;
}
template < class KeyType, class ValueType>
inline void ArrayDictionary<KeyType, ValueType>:: clear()
{
destroyDictionary();
}
template < class KeyType, class ValueType>
inline bool ArrayDictionary<KeyType, ValueType>::add(const KeyType& searchKey, const ValueType& newValue) throw (PrecondViolatedExcep)
{
bool ableToInsert = (entryCount < maxEntries);
if (ableToInsert)
{
// Make room for new entry by shifting all entries at
// positions >= newPosition toward the end of the array
// (no shift if newPosition == itemCount + 1). Performing
// a binary search doesn’t help here, because we need to
// shift the entries while looking for the insertion location.
int index = entryCount;
// Short-circuit evaluation is important
while ((index > 0) && (searchKey < items[index - 1].getKey()))
{
items[index] = items[index - 1];
index--;
} // end while
if (searchKey != items[index - 1].getKey())
{
items[index] = Entry<KeyType, ValueType>(searchKey, newValue);
entryCount++;
}
else
{
auto message = "Attempt to add entry whose search key exits in dictionary.";
throw (PrecondViolatedExcep(message);
}
return ableToInsert;
} // end add
}
template < class KeyType, class ValueType>
inline bool ArrayDictionary<KeyType, ValueType>:: remove(const const KeyType& itemKey)
{
int currentIndex = findEntryIndex(0, itemCount - 1, itemKey);
bool deletable = !isEmpty() && (currentIndex >= 0);
if (deletable)
{
while (currentIndex < entryCount - 1)
{
items[currentIndex] = items[currentIndex + 1];
currentIndex++;
}
itemCount--;
}
return deletable;
}
template < class KeyType, class ValueType>
inline ValueType getValue(const KeyType& searchKey) throw(NotFoundException)
{
int currentIndex = findEntryIndex(0, itemCount - 1, searchKey);
if (currentIndex < 0)
throw NotFoundException("nnItemis not in the Dictionary!nn");
return items[currentIndex].getItem();
}
template < class KeyType, class ValueType>
inline bool contains(const KeyType& searchKey)
{
return (findEntryIndex(0, entryCount - 1, itemKey) >= 0)
}
template < class KeyType, class ValueType>
inline void traverse(void visit(ValueType&))
{
for (int itr = 0; itr < entryCount; itr++)
{
ValueType currentItem = items[itr].getItem();
visit(currentItem);
}
}
I would like to dump the content inside the object tmp_np which is a UllmanSet which if you know a key then you know the position and if you know the position , you know the key. Is there a standard C++ container that's similar to the Ullmanset. Ullmanset 's index starts at 0 and Ullmanset1's index start at 1.
and also dump the content of frontierq which is a PriorityQ class.
UllmanSet tmp_np;
template<unsigned B>
class BasedUllmanSet
{
size_t n;
std::vector<int> key;
BasedVector<unsigned, B> pos;
public:
BasedUllmanSet()
: n(0)
{}
BasedUllmanSet(size_t cap)
: n(0), key(cap), pos(cap)
{}
size_t capacity() const { return key.size(); }
size_t size() const { return n; }
bool empty() const { return n == 0; }
void clear() { n = 0; }
void resize(size_t cap)
{
key.resize(cap);
pos.resize(cap);
n = 0;
}
bool contains(int k) const
{
unsigned p = pos[k];
return (p < n
&& key[p] == k);
}
void insert(int k)
{
if (contains(k))
return;
unsigned p = n++;
key[p] = k;
pos[k] = p;
}
void extend(int k)
{
assert(!contains(k));
unsigned p = n++;
key[p] = k;
pos[k] = p;
}
void erase(int k)
{
if (!contains(k))
return;
unsigned p = pos[k];
--n;
if (p != n)
{
int ell = key[n];
pos[ell] = p;
key[p] = ell;
}
}
int ith(int i)
{
assert(i >= 0 && i < (int)n);
return key[i];
}
};
using UllmanSet = BasedUllmanSet<0>;
using UllmanSet1 = BasedUllmanSet<1>;
The priority queue is implemented as followed. I like to print out the values inside the queue using std::cout.
PriorityQ<std::pair<int, int>, Comp> frontierq;
class Comp
{
public:
Comp() {}
bool operator()(const std::pair<int, int> &lhs,
const std::pair<int, int> &rhs) const
{
return (lhs.second > rhs.second
|| (lhs.second == rhs.second
&& lhs.first > rhs.first));
}
};
class PriorityQ
{
public:
Comp comp;
std::vector<T> v;
unsigned n;
public:
PriorityQ() : n(0) {}
PriorityQ(Comp comp_) : comp(comp_), n(0) {}
size_t size() const { return n; }
void clear() { n = 0; }
bool empty() { return n == 0; }
void push(const T &x)
{
assert(v.size() >= n);
if (v.size() == n)
v.push_back(x);
else
v[n] = x;
++n;
std::push_heap(&v[0], &v[n], comp);
}
const T &pop()
{
assert(n > 0);
std::pop_heap(&v[0], &v[n], comp);
--n;
return v[n];
}
const T &top()
{
assert(n > 0);
return v[0];
}
};
C++ standard containers do get this esoteric. If you have another question about the priority queue you should make another post.
I'm trying to pass an object and a vector of class objects or two objects to two overloaded template functions named checkPosition.
No matter what I try, changing my function to passing by value / reference / pointer / const / not const, it gives me the error;
Error: no instance of overloaded function "Room::checkPosition" matches the argument list
argument types are: (const Player, const std::vector< Monster, std::allocator< Monster > > )
object type is: const Room.
From Room.h:
class Room
{
public:
Player player;
std::vector<Monster> monster;
std::vector<Wall> wall;
std::vector<Exit> exit;
template<class T1> void xSet( T1 &object, const int &input );
template<class T2> void ySet( T2 &object, const int &input );
template<class T3> int x( T3 &object );
template<class T4> int y( T4 &object );
template<class T5> bool checkPosition( const T5 &object1, const T5 &object2 );
template<class T6> bool checkPosition( const T6 &object1, const std::vector<T6> &object2 );
void objectIconSet( );
void lengthSet( const int &input );
void widthSet( const int &input );
int length( );
int width( );
void staticDataMap( );
void completeDataMap( );
char staticDataMap( int x, int y );
char completeDataMap( int x, int y );
private:
int _length;
int _width;
std::vector< std::vector<char> > _staticDataMap;
std::vector< std::vector<char> > _completeDataMap;
};
From Room.cpp
template<class T5> bool Room::checkPosition( const T5 &object1, const T5 &object2 )
{
if( object1.position.x == object2.position.x &&
object1.position.y == object2.position.y )
{
return true
}
return false;
}
template<class T6> bool Room::checkPosition( const T6 &object1, const std::vector<T6> &object2 )
{
for( int i = 0; i < object2.size( ); i++ )
{
if( object1.position.x == object2[i].position.x &&
object1.position.y == object2[i].position.y )
{
return true
}
}
return false;
}
Examples of function use in main.cpp:
bool checkWinCondition( const Room &room )
{
if( room.checkPosition( room.player, room.exit ) == true )
{
std::cout << "\nYou win!";
return true;
}
return false;
}
bool checkLoseCondition( const Room &room )
{
if( room.checkPosition( room.player, room.monster ) == true )
{
std::cout << "\nYou lose!";
return true;
}
return false;
}
void SetRoomOuterWalls( Room &room )
{
Position tempPosition;
Wall tempWall;
for( int y = 0; y < room.length( ); y++ )
{
for( int x = 0; x < room.width( ); x++ )
{
tempPosition.x = x;
tempPosition.y = y;
if( room.checkPosition( tempPosition, room.exit ) == true )
{
continue;
}
else if( x == 0 || x == room.width( ) - 1 ||
y == 0 || y == room.length( ) - 1 )
{
room.wall.push_back( tempWall );
room.xSet( room.wall, x );
room.xSet( room.wall, y );
}
}
}
}
You are calling your function with two different parameters but your function is templated to one type
template<class T6> bool checkPosition( const T6 &object1, const std::vector<T6> &object2 );
Means that that you want an object and a vector of objects of the same type. You are passing into the function a player and a vector<monster> which does not match. What you can do is change your template to:
template<class T, class Y> bool checkPosition( const T &object1, const std::vector<Y> &object2 );
Which will allow you to take some object and a vector of the same type or another type.
i have to basically edit a quadratic probing file to work as a hash_map library but i'm having trouble overloading the subscript operator so i can modify that specefic index.
the code i have so far is:
template <typename HashedObj, typename storedObj >
class HashTable
{
public:
int& operator [] (const int nIndex)
{
return array[nIndex];//THIS IS WHATS WRONG
}
//create hashtable with siz of 101
explicit HashTable(int size = 101) : array( nextPrime( size ) )
{ makeEmpty( ); }
//return true if current index is active
bool contains( const HashedObj & x ) const
{
return isActive( findPos( x ) );
}
//initiallize index as empty
void makeEmpty( )
{
currentSize = 0;
for( int i = 0; i < array.size( ); i++ )
array[ i ].info = EMPTY;
}
//insert object into hash index and mark index as active
bool insert( const HashedObj & x )
{
// Insert x as active
int currentPos = findPos( x );
if( isActive( currentPos ) )
return false;
array[ currentPos ] = HashEntry( x, ACTIVE );
if( ++currentSize > array.size( ) / 2 )
rehash( );
return true;
}
//search for obj and mark index as deleted
bool remove( const HashedObj & x )
{
int currentPos = findPos( x );
if( !isActive( currentPos ) )
return false;
array[ currentPos ].info = DELETED;
return true;
}
//declare three different entry types
enum EntryType { ACTIVE, EMPTY, DELETED };
private:
//each hash index stores the following
struct HashEntry
{
//THIS WILL BE STRINGS OR INTS
HashedObj element;
//THIS WILL BE VECTOR STRINGS
storedObj ilement;
//index status is stored
EntryType info;
//each entry is made of hashed obj and stored obj and the status is empty
HashEntry( const HashedObj & e = HashedObj( ), const storedObj & f = storedObj( ),EntryType i = EMPTY )
: element( e ), ilement( f ),info( i ) { }
};
//create an array of hashentries
vector<HashEntry> array;
//currentsize of the hash table is stored here
int currentSize;
bool isActive( int currentPos ) const
{ return array[ currentPos ].info == ACTIVE; }
int findPos( const HashedObj & x ) const
{
int offset = 1;
int currentPos = myhash( x );
while( array[ currentPos ].info != EMPTY &&
array[ currentPos ].element != x )
{
currentPos += offset; // Compute ith probe
offset += 2;
if( currentPos >= array.size( ) )
currentPos -= array.size( );
}
return currentPos;
}
void rehash( )
{
vector<HashEntry> oldArray = array;
// Create new double-sized, empty table
array.resize( nextPrime( 2 * oldArray.size( ) ) );
for( int j = 0; j < array.size( ); j++ )
array[ j ].info = EMPTY;
// Copy table over
currentSize = 0;
for( int i = 0; i < oldArray.size( ); i++ )
if( oldArray[ i ].info == ACTIVE )
insert( oldArray[ i ].element );
}
int myhash( const HashedObj & x ) const
{
int hashVal = hashing( x );
hashVal %= array.size( );
if( hashVal < 0 )
hashVal += array.size( );
return hashVal;
}
};
int hashing( const string & key );
int hashing( int key );
the point is for main code to be able to do something like:
wordsByLength[words[i].length()] = words[i];
where words[i] will be a vector. i'm also assuming that i will need to modify the = operator later on but i'm not so sure
Think about what your subscript operator shall return. Is it int&? The simplest choice would be HashEntry:
template <typename HashedObj, typename storedObj >
class HashTable
{
public:
HashEntry& operator [] (int nIndex) // read/write version
{
return array[nIndex];
}
const HashEntry& operator [] (int nIndex) const // read only version
{
return array[nIndex];//THIS IS WHATS WRONG
}
...
};
But it is private. So either make it public - but this breaks somehow your encapsulation.
Because your are inserting HashedObj - then probably this is your desired return type:
template <typename HashedObj, typename storedObj >
class HashTable
{
public:
HashedObj& operator [] (int nIndex) // read/write version
{
return array[nIndex].element;
}
const HashedObj& operator [] (int nIndex) const // read only version
{
return array[nIndex].element;
}
...
};