Archicad C++ API
About Archicad add-on development using the C++ API.
SOLVED!

Hashable struct for the GS::HashTable<Key, Value>

Mihalcea Bogdan
Contributor

Hi,

I need to create a struct that can be used as a Key in a hashtable. 

So far I made this:

struct Item{
		GS::UInt8 parentId;
		GS::UInt8 itemId;
		const GS::UInt8 hash = this->parentId + this->itemId;

		GS::ULong Item::GenerateHashValue() {
			return GS::GenerateHashValue(this->hash);
		}
		bool operator== (const Item& other) const {
			return (this->parentId == other.parentId && this->itemId == other.itemId);
		}
	};

It gives me the error:

Does not have a GenerateHashValue member or non-member function. I am pretty sure I have GenerateHashValue.

Can you please point some directions on this matter?

1 ACCEPTED SOLUTION

Accepted Solutions
Solution
Oleg
Expert

Fast tests. Works for me. VisualStudio.
Using test is:

 

GS::HashTable<Item,int> table;
Item itm = { 10, 20 };
table.Add(itm, 2);
table[itm] = 3;

 


AC24 (you need const qualifier)

 

GS::ULong Item::GenerateHashValue() const 
{
	return GS::GenerateHashValue(this->hash);
}

 

 

AC25 (dont have time to study it )

 

GS::ULong Item::GenerateHashValue() const 
{
	return GS::CalculateHashValue(this->hash);
}

 

 

And just reply. Are you shure to use summary Ids for hashe generation ?
May be beter like this:

 

GS::ULong Item::GenerateHashValue() const 
{
	return ((ULong) parentId << 8 ) | itemId;
}

 

View solution in original post

9 REPLIES 9
Mihalcea Bogdan
Contributor

I know how to make it work with c++ standard std::unordered_map

struct Item
{
	int parentId;
	short itemId;

	bool operator==(const Item &other) const
	{
		return (parentId == other.parentId && itemId == other.itemId);
	}
};

template <>
struct std::hash<Item>
{
	std::size_t operator()(const Item& k) const
	{
		return (k.itemId + k.parentId);
	}
};

with the above struct I can use the following:

Item itm = { 10, 20 };
Item itm2 = { 10, 20 };
std::unordered_map<Item, int> hashMap;
hashMap[itm] = 10;
hashMap[itm2] = 30;
std::cout << hashMap[itm2] << std::endl;

Output will be 30.

I think you need to mplement the GenerateHashValue as non member function.

GS::ULong GenerateHashValue( const Item& item )
{
	return GS::GenerateHashValue( item.parentId + item.itemId );
}

And I guess there is other variant.
Inherit your Item from GS::Hashable and implement virtual member 
virtual ULong GenerateHashValue (void) const = 0;

like this

 

struct Item : public GS::Hashable
{
	virtual ULong	GenerateHashValue (void) const { return this->hash; }
}

 

 

It says it is already declared in the .obj file. GIS is my namespace.

Error LNK2005 "unsigned int __cdecl GIS::GenerateHashValue(struct GIS::Item const &)" (?GenerateHashValue@GIS@@YAIAEBUItem@1@@Z) already defined in AddOnMain.obj AddOn \polyGIS\Build\Source.obj 

 

I can't find the GS::Hashable class. 

Oleg
Expert

Sorry.  I worked on old project and checked it for old API.
It seem GS::Hashable was before AC24  and implementation of the HashTable was changed.
I will try it for API 24 and 25 later.

I was looking at other data structures which work with the GS::hashTable, the GS::Pair<T1, T2>. It has an implementation of the  GenerateHashValue() like you said.

//This is from the GS::Pair<>
template <class Type1, class Type2>
ULong	GenerateHashValue (const Pair<Type1, Type2>& pair)
{
	return GS::GenerateHashValue (pair.first, pair.second);
}
Solution
Oleg
Expert

Fast tests. Works for me. VisualStudio.
Using test is:

 

GS::HashTable<Item,int> table;
Item itm = { 10, 20 };
table.Add(itm, 2);
table[itm] = 3;

 


AC24 (you need const qualifier)

 

GS::ULong Item::GenerateHashValue() const 
{
	return GS::GenerateHashValue(this->hash);
}

 

 

AC25 (dont have time to study it )

 

GS::ULong Item::GenerateHashValue() const 
{
	return GS::CalculateHashValue(this->hash);
}

 

 

And just reply. Are you shure to use summary Ids for hashe generation ?
May be beter like this:

 

GS::ULong Item::GenerateHashValue() const 
{
	return ((ULong) parentId << 8 ) | itemId;
}

 

I was pretty sure that there will be no conflict. Now that I think more about it will not work.  Your solution works for me too, I forgot about the const, it is the same behavior as with operator overriding. Thank you very much!

Didn't find the answer?

Check other topics in this Forum

Back to Forum

Read the latest accepted solutions!

Accepted Solutions

Start a new conversation!