CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    May 2013
    Posts
    11

    Hashing problem with overloaded operator

    I've got a hasing template function that is giving me the error '!=' : no operator found which takes a left-hand operand of type 'StateData' (or there is no acceptable conversion). I have a StateData class that I've overloaded the != operator once as a friend and another time as a member of the class. Still, I get the same error. I'm at a loss as to why this is happening. Please help!

    StateData
    Code:
    class StateData
    {
    public:
    	StateData();
    	StateData(string, string, int, int);
    	void setStateInfo(string, string, int, int);
    	string getName();
    	string getCapitol();
    	int getYearAdmit();
    	int getOrder();
    	StateData getStateData();
    
    	friend bool operator<(StateData &, StateData &);
    	friend bool operator>(StateData &, StateData &);
    //	friend bool operator!=(StateData &, StateData &);
    	bool operator!=(StateData &);
    	friend bool operator==(StateData &, StateData &);
    	friend ostream &operator <<(ostream&, StateData);
    	friend istream &operator>>(istream &, StateData &);
    
    private:
    	string name;
    	string capitol;
    	int yearAdmit;
    	int order;
    
    };
    StateData functions
    Code:
    	StateData::StateData()
    	{
    		name = " ";
    		capitol = " ";
    		yearAdmit = 0;
    		order = 0;
    	}
    
    	StateData::StateData(string n, string c, int y, int o)
    	{
    		name = n;
    		capitol = c;
    		yearAdmit = y;
    		order = o;
    	}
    
    	void StateData::setStateInfo(string n, string c, int y, int o)
    	{
    		name = n;
    		capitol = c;
    		yearAdmit = y;
    		order = o;
    	}
    
    	string StateData::getName()
    	{        return name;          }
    
    	string StateData::getCapitol()
    		{        return capitol;          }
    
    	int StateData::getYearAdmit()
    		{        return yearAdmit;          }
    
    	int StateData::getOrder()
    		{        return order;          }
    
    	//StateData StateData::getStateData()
    	//	{        return this;          }
    
    	bool operator<(StateData &right, StateData &left)
    	{          return (right.getName() < left.getName());     }
    
    	bool operator>(StateData &right, StateData &left)
    	{          return (right.getName() > left.getName());     }
    
    	bool operator==(StateData &right, StateData &left)
    	{          return (right.getName() == left.getName());     }
    
    	//bool operator!=(StateData &right, StateData &left)
    	//{          return (right.getName() != left.getName());     }
    
    	bool StateData::operator!=(StateData &left)
    	{          return (this->name != left.name);     }
    
    
    	ostream &operator <<(ostream& out, StateData &a)
    	{
    		out << "State name: " << a.getName() << endl;
    		out << "State capitol: " << a.getCapitol() << endl;
    		out << "Year of admittance: " << a.getYearAdmit() << endl;
    		out << "Order of admittance: " << a.getOrder() << endl;
    		return out;
    	}
    
    	istream &operator>>(istream &in, StateData &a)
    	{
    		string n, c;
    		int y, o;
    		cout << "Enter State name: ";
    		getline(cin, n);
    		cout << "Enter State capitol: ";
    		getline(cin, c);
    		cout << "Enter year of admittance: ";
    		cin >> y;
    		cout << "Enter order of admittance: ";
    		cin >> o;
    		a.setStateInfo(n, c, y, o);
    		return in;
    	}
    hashT class
    Code:
    template<class elemType>
    class hashT
    {
    private:
        elemType *HTable;		//pointer to the hash table
        int *indexStatusList;	//pointer to the array indicating
    							//the status of a position in the
    							//hash table
        int length;				//number of items in the hash table
        int HTSize;				//maximum size of the hash table
    };
    insert function - where error occurs
    Code:
    template <class elemType>
    void hashT<elemType>::insert(int hashIndex, const elemType& rec)
    {
    	int pCount;
    	int inc;
    
    	pCount = 0;
    	inc = 1;
    
    	while(indexStatusList[hashIndex] == 1
    		  && HTable[hashIndex] != rec
    		  && pCount < HTSize / 2)
    	{
    		cout <<"inc = " << inc << endl;
    		pCount++;
    		hashIndex = (hashIndex + inc ) % HTSize;
    		cout << "new hashIndex = " << hashIndex << endl;
    		inc = inc + 2;
    	}
    
    
    	if(indexStatusList[hashIndex] != 1)
    	{
    		HTable[hashIndex] = rec;
    		cout << "HTable["<< hashIndex <<"]" <<" = " << rec << endl;
    		indexStatusList[hashIndex] = 1;
    		length++;
    	}
    	else
    		if(HTable[hashIndex] == rec)
    			cerr<<"Error: No duplicates are allowed"<<endl;
    		else
    			cerr<<"Error: The table is full. "
    			    <<"Unable to resolve the collision"<<endl;
    }
    here is the main
    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    #include "hashT.h"
    #include "stateData.h"
    
    using namespace std;
    
    int hashFunc(string name, int size);
    
    int main()
    {
    	hashT<StateData> HashTable(50);
    	int size = 15;
    
    	ifstream infile;
    
    	infile.open("states.txt");
    	if(!infile)
    	{
    		cout << "Error reading states file.\n";
    		exit(1);
    	}
    
    	char ch;
    	int year, order, key;
    	string state, capitol;
    	bool found;
    
    	getline(infile, state);
    
    	while(infile)
    	{
    		getline(infile, capitol);
    		infile >> year;
    		infile >> order;
    		StateData temp;
    		temp.setStateInfo(state, capitol, year, order);
    		infile.get(ch);
    		key = hashFunc(state, size);
    		HashTable.insert(key, temp);
    
    		getline(infile, state);
    	}
    
    	HashTable.print();
    
    	//cout<<"Enter item to be deleted: ";
    	//cin>>num;
    	//cout<<endl;
    
    	infile.close();
    	system("pause");
    	return 0;
    
    }
    
    int hashFunc(string name, int size)
    {
    	int i, sum, len;
    	i= 0;
    	sum = 0;
    	len = name.length();
    	for (int k=0; k < 15 - len; k++)
    		name = name + ' ';
    	for (int k = 0; k < 5; k++)
    	{
    		sum = sum + static_cast<int>(name[i]) * 128 * 128
    			+ static_cast<int>(name[i+1]) * 128
    			+ static_cast<int>(name[i+2]);
    		i = i+3;
    	}
    	return sum % size;
    }

  2. #2
    Join Date
    May 2009
    Posts
    2,413

    Re: Hashing problem with overloaded operator

    Here,

    void hashT<elemType>::insert(int hashIndex, const elemType& rec)

    elemType (which is a StateData) is passed by const reference, whereas here

    // friend bool operator!=(StateData &, StateData &);
    bool operator!=(StateData &);

    it's passed by reference only (without the const). So in effect you have no fitting operator!= signature.

    It's easy to test whether this is the problem. You just remove const here like,

    void hashT<elemType>::insert(int hashIndex, elemType& rec)

    and it should work.

  3. #3
    Join Date
    May 2013
    Posts
    11

    Re: Hashing problem with overloaded operator

    That fixed it! Thank you so much! One more question, maybe I could use the friend function and change the StateData objects to const reference?

  4. #4
    Join Date
    May 2009
    Posts
    2,413

    Re: Hashing problem with overloaded operator

    Quote Originally Posted by luvCats View Post
    That fixed it! Thank you so much! One more question, maybe I could use the friend function and change the StateData objects to const reference?
    Yes, you can do that. I would use a friend function with parameters by const reference. Const reference is the preferred passing mode if you don't intend to change the parameters.

    What I suggested was only because it was the easiest way to quickly test whether this was the problem.

  5. #5
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Hashing problem with overloaded operator

    Also, when designing your own containers, you ideally want to attempt to design your conatiner class in such a way that you only need ONE comparator/ordering operator.

    If you look at the STL implementations, all the "weak ordering" containers and functions only use an < operator. Handy for those using the class since they only need to provide a single operator function as well.

    Here you have a <, >, !=, ==
    They might be needed for other things, but from a pure pov of the container, you want to avoid this.

    Additionally, it may also be interesting to templatize the comparator/ordering operator so you can overload it at template instantiation rather than only having the option to overload an operator in your element class. This could be important if you want to store classes that don't come with an operator and which you can't change, and where deriving may be awkward or even unfeasible. Have a look at std::map to see how they templatize the comparator to default to less<Key>...
    Last edited by OReubens; May 28th, 2013 at 11:06 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured