Link to home
Start Free TrialLog in
Avatar of oxygen_728
oxygen_728

asked on

Microsoft Visual C++ 9.0 (2008) -- hash_set with custom object example needed

Hello,

I've asked a similar question before, but I got answers from different compilers. I've had great difficulty setting up a hash_set with a custom object.

My Goals:

- Have a custom class (RubiFont2)
- Create a hash_set of RubiFont2 instances
- It must compile on Visual Studio 2008 (this is the hard part because hash_set isn't in the c++ standard!)

Feel free to reference the old question: https://www.experts-exchange.com/questions/23131724/c-hash-set-with-a-custom-object.html

At
Avatar of oxygen_728
oxygen_728

ASKER

Attached is RubiFont2 including its implemented functions


class RubiFont2{
public:
	char* face;
	ID3DXFont *MyFont;
	UINT FontHeight;
	UINT FontWeight;
	UINT MipLevels;
	bool	italics;
	DWORD CharSet;
	DWORD OutputPrecision;
	DWORD Quality;
	DWORD PitchAndFamily;
	char* hash_string;
 
	friend bool operator==(const RubiFont2& l, const RubiFont2& r);
	friend bool operator<(const RubiFont2& l, const RubiFont2& r);
	RubiFont2() { init(); } // default constructor
	RubiFont2(const RubiFont2& r);
	RubiFont2& operator=(const RubiFont2& r);
	void	init();
	void copy(const RubiFont2& r);
	void	SetupD3DXFont();
	size_t hash() const;
	//Comparison function so that this sucker can be used in std set's
 
	int DrawTextA( LPD3DXSPRITE pSprite, LPCSTR pString, int Count, LPRECT pRect, DWORD Format, D3DCOLOR Color);
	RubiFont2(  LPDIRECT3DDEVICE9 pDevice,  INT Height,  UINT Width,  UINT Weight,  UINT MipLevels,  BOOL Italic,  DWORD CharSet,  DWORD OutputPrecision,
		DWORD Quality,  DWORD PitchAndFamily,  LPCTSTR pFacename);
	~RubiFont2();
 
	static RubiFont2* CreateRubiFont2(LPDIRECT3DDEVICE9 pDevice,  INT Height,  UINT Width,  UINT Weight,  UINT MipLevels,  BOOL Italic,  DWORD CharSet,  DWORD OutputPrecision,
		DWORD Quality,  DWORD PitchAndFamily,  LPCTSTR pFacename);
 
 
	hash_set<RubiFont2, FontHasher>::iterator RIT;
};
 
 
 
 
bool operator<(const RubiFont2& l, const RubiFont2& r){
	return memcmp(l.hash_string, r.hash_string, 62) < 0;
}
 
bool operator==(const RubiFont2& l, const RubiFont2& r){
	return memcmp(l.hash_string, r.hash_string, 62) == 0;
}
 
size_t RubiFont2::hash() const {                           // <--- this will be the hash_string function used
	double d = 0.0;
	for(int i = 0; i < 62; i++){
		d += (double)((int)hash_string[i]);
	}
	return (int)d;                                     // <--- just a stupid test hash_string function now
}
 
void RubiFont2::copy(const RubiFont2& r) {
  //copy code
  }
 
RubiFont2::RubiFont2(const RubiFont2& r){
	copy(r);
}
 
RubiFont2& RubiFont2::operator=(const RubiFont2& r){ 
	copy(r); 
	return *this;
}
 
void RubiFont2::init() {
     // init code
  }
 
 
int RubiFont2::DrawTextA(LPD3DXSPRITE pSprite, LPCSTR pString, int Count, LPRECT pRect, DWORD Format, D3DCOLOR Color){
	return MyFont->DrawTextA(pSprite, pString, Count, pRect, Format, Color);
}
 
 
RubiFont2::RubiFont2(  LPDIRECT3DDEVICE9 pDevice,  INT Height,  UINT Width,  UINT Weight,  UINT pMipLevels,  BOOL pItalic,  DWORD pCharSet,  DWORD pOutputPrecision,
				   DWORD pQuality,  DWORD pPitchAndFamily,  LPCTSTR pFacename){
 
	//init code
}
 
void RubiFont2::SetupD3DXFont(){
	//font code
}
 
RubiFont2* RubiFont2::CreateRubiFont2(LPDIRECT3DDEVICE9 pDevice,  INT Height,  UINT Width,  UINT Weight,  UINT MipLevels,  BOOL Italic,  DWORD CharSet,  DWORD OutputPrecision, 
								   DWORD Quality,  DWORD PitchAndFamily,  LPCTSTR pFacename){
	
	 //init code
}
 
RubiFont2::~RubiFont2(){
	delete[] face;
	delete[] hash_string;
	//if ( MyFont )
		//MyFont->Release();
}

Open in new window

Attached is a sample declaration of a RubiFont2 hash_set and also listed is a compare class.
hash_set<RubiFont2, FontHasher>::iterator RIT;
 
class FontHasher : public stdext::hash_compare <RubiFont2>
{
public:
  size_t operator() (const RubiFont2& p) const
  // This is the hash function itself
  {
    return p.hash();
  }
 
  bool operator() (const RubiFont2& p1, const RubiFont2& p2) const
  // This is a comparison operator. It is needed by the hashed container
  {
    return p1 == p2;
  }
};

Open in new window

Note: My code doesn't work - I'm missing something serious -- I get long-winded template errors

I've scoured the internet for a hash_set example, but to no avail (I mean hash_set examples with custom objects)
Avatar of jkr
Could you post the error message and the indicate which line(s) in your code are referenced?
The first error is derived from the line:

      hash_set<RubiFont2, FontHasher>::iterator RIT;

I think the others are related to that - but thats the only one i can trace to a line of my code
1>------ Build started: Project: Raptor, Configuration: Debug Win32 ------
1>Compiling...
1>headers.cpp
1>d:\program files\microsoft directx sdk (december 2006)\include\strsafe.h(5595) : warning C4996: '_vsnprintf': This function or variable may be unsafe. Consider using _vsnprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        d:\program files\microsoft visual studio 9.0\vc\include\stdio.h(358) : see declaration of '_vsnprintf'
1>d:\program files\microsoft directx sdk (december 2006)\include\strsafe.h(5635) : warning C4996: '_vsnwprintf': This function or variable may be unsafe. Consider using _vsnwprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        d:\program files\microsoft visual studio 9.0\vc\include\stdio.h(483) : see declaration of '_vsnwprintf'
1>d:\program files\microsoft directx sdk (december 2006)\include\strsafe.h(5719) : warning C4996: '_vsnprintf': This function or variable may be unsafe. Consider using _vsnprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        d:\program files\microsoft visual studio 9.0\vc\include\stdio.h(358) : see declaration of '_vsnprintf'
1>d:\program files\microsoft directx sdk (december 2006)\include\strsafe.h(5871) : warning C4996: '_vsnwprintf': This function or variable may be unsafe. Consider using _vsnwprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        d:\program files\microsoft visual studio 9.0\vc\include\stdio.h(483) : see declaration of '_vsnwprintf'
1>d:\program files\microsoft visual studio 9.0\vc\include\hash_set(58) : error C2079: 'stdext::_Hset_traits<_Kty,_Tr,_Alloc,_Mfl>::comp' uses undefined class 'FontHasher'
1>        with
1>        [
1>            _Kty=RubiFont2,
1>            _Tr=FontHasher,
1>            _Alloc=std::allocator<RubiFont2>,
1>            _Mfl=false
1>        ]
1>        d:\program files\microsoft visual studio 9.0\vc\include\xhash(148) : see reference to class template instantiation 'stdext::_Hset_traits<_Kty,_Tr,_Alloc,_Mfl>' being compiled
1>        with
1>        [
1>            _Kty=RubiFont2,
1>            _Tr=FontHasher,
1>            _Alloc=std::allocator<RubiFont2>,
1>            _Mfl=false
1>        ]
1>        d:\program files\microsoft visual studio 9.0\vc\include\hash_set(67) : see reference to class template instantiation 'stdext::_Hash<_Traits>' being compiled
1>        with
1>        [
1>            _Traits=stdext::_Hset_traits<RubiFont2,FontHasher,std::allocator<RubiFont2>,false>
1>        ]
1>        d:\documents and settings\oxygen\desktop\raptor_hash_set\rubifont.h(78) : see reference to class template instantiation 'stdext::hash_set<_Kty,_Tr>' being compiled
1>        with
1>        [
1>            _Kty=RubiFont2,
1>            _Tr=FontHasher
1>        ]
1>d:\program files\microsoft visual studio 9.0\vc\include\xhash(156) : error C2027: use of undefined type 'FontHasher'
1>        d:\documents and settings\oxygen\desktop\raptor_hash_set\rubifont.h(5) : see declaration of 'FontHasher'
1>d:\program files\microsoft visual studio 9.0\vc\include\xhash(156) : error C2065: 'bucket_size' : undeclared identifier
1>d:\program files\microsoft visual studio 9.0\vc\include\xhash(157) : error C2027: use of undefined type 'FontHasher'
1>        d:\documents and settings\oxygen\desktop\raptor_hash_set\rubifont.h(5) : see declaration of 'FontHasher'
1>d:\program files\microsoft visual studio 9.0\vc\include\xhash(157) : error C2065: 'min_buckets' : undeclared identifier
1>Build log was saved at "file://d:\Documents and Settings\oxygen\Desktop\Raptor_hash_set\Debug\BuildLog.htm"
1>Raptor - 5 error(s), 4 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Open in new window

>> error C2079: 'stdext::_Hset_traits<_Kty,_Tr,_Alloc,_Mfl>::comp' uses undefined class 'FontHasher'

Did you define the FontHasher class after instantiating the iterator ? If so, make sure that the FontHasher class is BEFORE the line where you create the iterator.
Well, when I put a "class FontHasher;" at the top of the file, and define RubiFont2 first, I get the error that i pasted above.

However, when I simply move the definition of FontHasher to before the definition of RubiFont2, I get errors about use of an undefined type: RubiFont2 .. and that is despite the fact that the top of the file has a "class RubiFont2;"

So either way I get stuck
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Sorry, make that

class RubiFont2;

of course.
The following error occurs at the "return p.hash();" line

1>d:\documents and settings\oxygen\desktop\raptor_hash_set\rubifont.h(13) : error C2027: use of undefined type 'RubiFont2'


class RubiFont2;
 
class FontHasher : public stdext::hash_compare <RubiFont2>
{
public:
  size_t operator() (const RubiFont2& p) const
  // This is the hash function itself
  {
    return p.hash();
  }
 
  bool operator() (const RubiFont2& p1, const RubiFont2& p2) const
  // This is a comparison operator. It is needed by the hashed container
  {
    return p1 == p2;
  }
};

Open in new window

I think I need a quantum computer
Sorry, both function's bodies need to be removed from the header when using a foward declaration, i.e.
// FontHasher.h
 
// forward declaration. The type is now "incomplete", so be sure
// to *only* use declarative statements and no code (see below)
class RubiFont;
 
class FontHasher : public stdext::hash_compare <RubiFont2>
{
public:
  size_t operator() (const RubiFont2& p) const;
  // move the body to the .cpp file where you can #include "RubiFont.h"
 
  bool operator() (const RubiFont2& p1, const RubiFont2& p2)
  // move the body to the .cpp file where you can #include "RubiFont.h"
};
 
// FontHasher.cpp
 
#include "FontHasher"
#include "RubiFont2.h"
 
  size_t FontHasher::operator() (const RubiFont2& p) const
  // This is the hash function itself
  {
    return p.hash();
  }
 
  bool FontHasher::operator() (const RubiFont2& p1, const RubiFont2& p2) const
  // This is a comparison operator. It is needed by the hashed container
  {
    return p1 == p2;
  }

Open in new window

Thanks, that is the solution -- ran into some problems with circular references... don't need a quantum computer after all.

Attached is the working code for any  poor suckers like me that stumble by


Thanks all
//From Header File:
 
#include "headers.h"
 
class RubiFont2;
class FontHasher;
 
class FontHasher : public stdext::hash_compare <RubiFont2>
{
public:
  size_t operator() (const RubiFont2& p) const;
 
  bool operator() (const RubiFont2& p1, const RubiFont2& p2) const;
 
};
 
class RubiFont2{
public:
	//declarations omitted
 
	friend bool operator==(const RubiFont2& l, const RubiFont2& r);
	friend bool operator<(const RubiFont2& l, const RubiFont2& r);
	RubiFont2() { init(); } // default constructor
	RubiFont2(const RubiFont2& r);
	RubiFont2& operator=(const RubiFont2& r);
	void	init();
	void copy(const RubiFont2& r);
	void	SetupD3DXFont();
	size_t hash() const;
	//Comparison function so that this sucker can be used in std set's
 
	int DrawTextA( LPD3DXSPRITE pSprite, LPCSTR pString, int Count, LPRECT pRect, DWORD Format, D3DCOLOR Color);
	RubiFont2(  LPDIRECT3DDEVICE9 pDevice,  INT Height,  UINT Width,  UINT Weight,  UINT MipLevels,  BOOL Italic,  DWORD CharSet,  DWORD OutputPrecision,
		DWORD Quality,  DWORD PitchAndFamily,  LPCTSTR pFacename);
	~RubiFont2();
 
	static RubiFont2* CreateRubiFont2(LPDIRECT3DDEVICE9 pDevice,  INT Height,  UINT Width,  UINT Weight,  UINT MipLevels,  BOOL Italic,  DWORD CharSet,  DWORD OutputPrecision,
		DWORD Quality,  DWORD PitchAndFamily,  LPCTSTR pFacename);
 
 
	hash_set<RubiFont2, FontHasher>::iterator RIT;
};
 
 
 
 
// From CPP File
 
#include "headers.h"
 
//hash_set<RubiFont2>::iterator RubiFont2::RIT;
 
//const size_t hash_compare::bucket_size = 4;
//const size_t hash_compare::min_buckets = 8;
 
 
size_t FontHasher::operator() (const RubiFont2& p) const
// This is the hash function itself
{
return p.hash();
}
 
bool FontHasher::operator() (const RubiFont2& p1, const RubiFont2& p2) const
// This is a comparison operator. It is needed by the hashed container
{
return p1 == p2;
}
 
 
bool operator<(const RubiFont2& l, const RubiFont2& r){
	return memcmp(l.hash_string, r.hash_string, 62) < 0;
}
 
bool operator==(const RubiFont2& l, const RubiFont2& r){
	return memcmp(l.hash_string, r.hash_string, 62) == 0;
}
 
size_t RubiFont2::hash() const {                           // <--- this will be the hash_string function used
	double d = 0.0;
	for(int i = 0; i < 62; i++){
		d += (double)((int)hash_string[i]);
	}
	return (int)d;                                     // <--- just a stupid test hash_string function now
}
 
void RubiFont2::copy(const RubiFont2& r) {
	//copy code
  }
 
RubiFont2::RubiFont2(const RubiFont2& r){
	copy(r);
}
 
RubiFont2& RubiFont2::operator=(const RubiFont2& r){ 
	copy(r); 
	return *this;
}
 
void RubiFont2::init() {
    // init code
  }
 
 
int RubiFont2::DrawTextA(LPD3DXSPRITE pSprite, LPCSTR pString, int Count, LPRECT pRect, DWORD Format, D3DCOLOR Color){
	return MyFont->DrawTextA(pSprite, pString, Count, pRect, Format, Color);
}
 
 
RubiFont2::RubiFont2(  LPDIRECT3DDEVICE9 pDevice,  INT Height,  UINT Width,  UINT Weight,  UINT pMipLevels,  BOOL pItalic,  DWORD pCharSet,  DWORD pOutputPrecision,
				   DWORD pQuality,  DWORD pPitchAndFamily,  LPCTSTR pFacename){
 
	//init code
}
 
void RubiFont2::SetupD3DXFont(){
	if ( FAILED ( D3DXCreateFont( g_pd3dDevice, FontHeight * RubiciteUI::Screen_Pixel_Height / 10000.0, 0, FontWeight, MipLevels, italics, 
		CharSet, OutputPrecision, Quality, PitchAndFamily, face, &MyFont ) ) ){
		MessageBox(NULL, "Error Creating Font, Press OK to break", "Error Creating Font", MB_OK);
		int ii = 1;
	}
}
 
RubiFont2* RubiFont2::CreateRubiFont2(LPDIRECT3DDEVICE9 pDevice,  INT Height,  UINT Width,  UINT Weight,  UINT MipLevels,  BOOL Italic,  DWORD CharSet,  DWORD OutputPrecision, 
								   DWORD Quality,  DWORD PitchAndFamily,  LPCTSTR pFacename){
	
	RubiFont2 r(pDevice, Height, Width, Weight, MipLevels, Italic, CharSet, OutputPrecision, Quality, PitchAndFamily, pFacename);
	r.MyFont = NULL;
 
	//RIT = Fonts2.find(r);
 
	////This is a new font, Add it 
	//if ( RIT == Fonts2.end() ){
	//	r.SetupD3DXFont();
	//	Fonts2.insert(r);
 
		
 
		//string s = "";
		//for(RIT = Fonts2.begin(); RIT != Fonts2.end(); RIT++){
		//	s += (*RIT).hash_string;
		//	s += "\n";
		//}
		//MessageBox(NULL, s.c_str(), "Debuggin", MB_OK);
	//	RIT = Fonts2.find(r);
	//	return &(*RIT);
	//}else{
	//	return &(*RIT);
	//}
	return NULL;
}
 
RubiFont2::~RubiFont2(){
	delete[] face;
	delete[] hash_string;
	//if ( MyFont )
		//MyFont->Release();
}

Open in new window