Discussion:
'CMap' of 'CString' to 'CString'
(too old to reply)
Martin
2007-04-14 17:11:21 UTC
Permalink
Hello!

I'm trying to create a dictionary with both key and value of type
'CString'. I declare the object of 'CMap' so it is as closer to
std::map, as possible:

CMap<CString, const CString&, CString, const CString&> m_appLangs;

and semantically it's like this:

std::map<std::string, std::string> m_appLangs;

But it seems 'CMap' is not realized as an RB-tree, I guess it must be
realized through hash table. The problem is when I make the above
declaration, my source file refuse to compile. Here is the simplified
error message:

cannot convert from 'const CString' to 'DWORD_PTR'
see reference to function template instantiation 'UINT
HashKey<ARG_KEY>(ARG_KEY)' being compiled with
[ARG_KEY=const CString &]

Here is the code of 'HashKey' function from "afxtempl.h":

template<class ARG_KEY>
AFX_INLINE UINT AFXAPI HashKey(ARG_KEY key)
{
// default identity hash - works for most primitive values
return (DWORD)(((DWORD_PTR)key)>>4);
}

And what does it mean? Can't I create a map of string to string just
because there is no conversion from 'CString' to 'DWORD_PTR'? I think/
hope I'm wrong. Would you please show me my mistake?

Thanks in advance
Martin
David Wilkinson
2007-04-14 18:30:56 UTC
Permalink
Post by Martin
Hello!
I'm trying to create a dictionary with both key and value of type
'CString'. I declare the object of 'CMap' so it is as closer to
CMap<CString, const CString&, CString, const CString&> m_appLangs;
std::map<std::string, std::string> m_appLangs;
But it seems 'CMap' is not realized as an RB-tree, I guess it must be
realized through hash table. The problem is when I make the above
declaration, my source file refuse to compile. Here is the simplified
cannot convert from 'const CString' to 'DWORD_PTR'
see reference to function template instantiation 'UINT
HashKey<ARG_KEY>(ARG_KEY)' being compiled with
[ARG_KEY=const CString &]
template<class ARG_KEY>
AFX_INLINE UINT AFXAPI HashKey(ARG_KEY key)
{
// default identity hash - works for most primitive values
return (DWORD)(((DWORD_PTR)key)>>4);
}
And what does it mean? Can't I create a map of string to string just
because there is no conversion from 'CString' to 'DWORD_PTR'? I think/
hope I'm wrong. Would you please show me my mistake?
Martin:

Why not use std::map<CString, CString>? I think it will work. I never
use the MFC collection classes.
--
David Wilkinson
Visual C++ MVP
Martin
2007-04-14 17:45:21 UTC
Permalink
Post by David Wilkinson
Why not use std::map<CString, CString>? I think it will work. I never
use the MFC collection classes.
--
David Wilkinson
Visual C++ MVP
I'm going to, but first I want to be sure there is no worthy way with
'CMap'.
David Ching
2007-04-14 17:37:36 UTC
Permalink
Post by Martin
Hello!
I'm trying to create a dictionary with both key and value of type
'CString'. I declare the object of 'CMap' so it is as closer to
CMap<CString, const CString&, CString, const CString&> m_appLangs;
std::map<std::string, std::string> m_appLangs;
You can use the pre-made class CMapStringToString instead of creating your
own.
Post by Martin
But it seems 'CMap' is not realized as an RB-tree, I guess it must be
realized through hash table. The problem is when I make the above
declaration, my source file refuse to compile. Here is the simplified
cannot convert from 'const CString' to 'DWORD_PTR'
see reference to function template instantiation 'UINT
HashKey<ARG_KEY>(ARG_KEY)' being compiled with
[ARG_KEY=const CString &]
Not sure why this is, maybe it doesn't like either the "const" or the '&'.

-- David
Martin
2007-04-14 17:49:40 UTC
Permalink
Post by David Ching
Post by Martin
Hello!
I'm trying to create a dictionary with both key and value of type
'CString'. I declare the object of 'CMap' so it is as closer to
CMap<CString, const CString&, CString, const CString&> m_appLangs;
std::map<std::string, std::string> m_appLangs;
You can use the pre-made class CMapStringToString instead of creating your
own.
Post by Martin
But it seems 'CMap' is not realized as an RB-tree, I guess it must be
realized through hash table. The problem is when I make the above
declaration, my source file refuse to compile. Here is the simplified
cannot convert from 'const CString' to 'DWORD_PTR'
see reference to function template instantiation 'UINT
HashKey<ARG_KEY>(ARG_KEY)' being compiled with
[ARG_KEY=const CString &]
Not sure why this is, maybe it doesn't like either the "const" or the '&'.
-- David
Martin
2007-04-14 17:53:03 UTC
Permalink
Post by David Ching
You can use the pre-made class CMapStringToString instead of creating your
own.
Wow, I didn't know about it, thanks, I'll try it out.
Post by David Ching
Not sure why this is, maybe it doesn't like either the "const" or the '&'.
No, there is simply no coversion from 'CString' to 'DWORD_PTR'. To
make sure, I've removed 'const's and '&'s. Now the error message is:

cannot convert from 'CString' to 'DWORD_PTR'

Martin
Michael K. O'Neill
2007-04-14 19:01:28 UTC
Permalink
Post by Martin
Hello!
I'm trying to create a dictionary with both key and value of type
'CString'. I declare the object of 'CMap' so it is as closer to
CMap<CString, const CString&, CString, const CString&> m_appLangs;
std::map<std::string, std::string> m_appLangs;
But it seems 'CMap' is not realized as an RB-tree, I guess it must be
realized through hash table. The problem is when I make the above
declaration, my source file refuse to compile. Here is the simplified
cannot convert from 'const CString' to 'DWORD_PTR'
see reference to function template instantiation 'UINT
HashKey<ARG_KEY>(ARG_KEY)' being compiled with
[ARG_KEY=const CString &]
template<class ARG_KEY>
AFX_INLINE UINT AFXAPI HashKey(ARG_KEY key)
{
// default identity hash - works for most primitive values
return (DWORD)(((DWORD_PTR)key)>>4);
}
And what does it mean? Can't I create a map of string to string just
because there is no conversion from 'CString' to 'DWORD_PTR'? I think/
hope I'm wrong. Would you please show me my mistake?
Thanks in advance
Martin
When you use a CMap where CString is the key, you need to provide your own
hash function. The default one will not work/compile for a CString, as you
have discovered.

Here's one that has worked for me. I define it as global function:

// implementation of hash function

template< > UINT AFXAPI HashKey( CString& key )
{
LPCTSTR pp = (LPCTSTR)(key);
UINT uiRet = 0;
while (*pp)
{
uiRet = (uiRet<<5) + uiRet + *pp++;
}

return uiRet;
}


In the .h file for the class where you define the CMap (I'm assuming it's a
member variable), you will need a forward declaration of the function at the
top:

// forward declaration of hash function for the CMap

template< > UINT AFXAPI HashKey( CString& key );

Mike
Joseph M. Newcomer
2007-04-14 22:44:14 UTC
Permalink
There is no reason to expect CMap is a red/black tree implementation; in fact the term
does not appear anywhere in the descriptions of the CMap. It is just a hash table, and a
good indicator of this would be suspicioiusly-named InitHashTable method or the
equally-suspiciously-named Collection Helper function called HashKey, whose description is
that it creates a hash key.

For a CString, you have to create a HashKey helper function that computes the hash key
based on a function of the string (e.g., compute the CRC-32 of the characters, or
something else equally useful)
joe
Post by Martin
Hello!
I'm trying to create a dictionary with both key and value of type
'CString'. I declare the object of 'CMap' so it is as closer to
CMap<CString, const CString&, CString, const CString&> m_appLangs;
std::map<std::string, std::string> m_appLangs;
But it seems 'CMap' is not realized as an RB-tree, I guess it must be
realized through hash table. The problem is when I make the above
declaration, my source file refuse to compile. Here is the simplified
cannot convert from 'const CString' to 'DWORD_PTR'
see reference to function template instantiation 'UINT
HashKey<ARG_KEY>(ARG_KEY)' being compiled with
[ARG_KEY=const CString &]
template<class ARG_KEY>
AFX_INLINE UINT AFXAPI HashKey(ARG_KEY key)
{
// default identity hash - works for most primitive values
return (DWORD)(((DWORD_PTR)key)>>4);
}
And what does it mean? Can't I create a map of string to string just
because there is no conversion from 'CString' to 'DWORD_PTR'? I think/
hope I'm wrong. Would you please show me my mistake?
Thanks in advance
Martin
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Loading...