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: http://www.experts-exchange.com/Programming/Languages/CPP/Q_23131724.html

At
oxygen_728Asked:
Who is Participating?
 
jkrConnect With a Mentor Commented:
That's a typical problem for circular references. What you can do is

// 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
  // This is the hash function itself
  {
    return p.hash();
  }
 
  bool operator() (const RubiFont2& p1, const RubiFont2& p2)
  // move the body to the .cpp file where you can #include "RubiFont.h"
};

Open in new window

0
 
oxygen_728Author Commented:
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

0
 
oxygen_728Author Commented:
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

0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
oxygen_728Author Commented:
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)
0
 
jkrCommented:
Could you post the error message and the indicate which line(s) in your code are referenced?
0
 
oxygen_728Author Commented:
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

0
 
Infinity08Commented:
>> 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.
0
 
oxygen_728Author Commented:
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
0
 
jkrCommented:
Sorry, make that

class RubiFont2;

of course.
0
 
oxygen_728Author Commented:
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

0
 
oxygen_728Author Commented:
I think I need a quantum computer
0
 
jkrCommented:
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

0
 
oxygen_728Author Commented:
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

0
All Courses

From novice to tech pro — start learning today.