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?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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
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
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

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:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.