4

I'm trying to create following unordered_map:

std::unordered_map<CString, CString, std::function<size_t(const CString &data)>> usetResponse(100, [](const CString &data)
    {
        return std::hash<std::string>()((LPCSTR)data);
    });

I provided hash function for CString, but compiler still returns errors:

error C2338: The C++ Standard doesn't provide a hash for this type. 

error C2664: 'std::unordered_map<CString,CString,std::hash<_Kty>,std::equal_to<_Kty>,std::allocator<std::pair<const
_Kty,_Ty>>>::unordered_map(std::initializer_list<std::pair<const _Kty,_Ty>>,unsigned int,const std::hash<_Kty> &,const _Keyeq &,const std::allocator<std::pair<const _Kty,_Ty>> &)' : cannot convert argument 1 from 'std::unordered_map<CString,CString,std::function<size_t (const CString &)>,std::equal_to<_Kty>,std::allocator<std::pair<const
_Kty,_Ty>>>' to 'const std::unordered_map<CString,CString,std::hash<_Kty>,std::equal_to<_Kty>,std::allocator<std::pair<const
_Kty,_Ty>>> &'

Please tell me what I'm doing wrong ?

drewpol
  • 665
  • 1
  • 6
  • 26
  • What happens if you pass a non-lambda hash function? Same error? – Gillespie Jan 09 '18 at 21:42
  • Please edit your question to contain [mcve] – Slava Jan 09 '18 at 21:45
  • Read the error message more carefully: "*cannot convert argument 1 from 'std::unordered_map,...>' to 'const std::unordered_map,...> &*"'. That means you are trying to pass an instance of your custom `unordered_map` type to a function parameter taking a standard `unordered_map` type. Template parameters are part of the class type, so you can't mix types that use different template parameters. You need to write a specialization of `std::hash` instead of using a custom hash as the template parameter – Remy Lebeau Jan 09 '18 at 21:56
  • Is there any reason to not use CMapStringToString ? https://msdn.microsoft.com/en-us/library/ddw782e0.aspx – Flaviu_ Jan 10 '18 at 09:10
  • This object needs to be returned by function but MFC containers doesn't have default copy-ctor. In this case I don't want to create wrapper for this purpose. – drewpol Jan 10 '18 at 12:02

1 Answers1

5

Something like this:

struct CStringHash
{
    size_t operator () (const CString &s) const
    {
        return hash<string>()(static_cast<LPCSTR>(s));
    }
};

Then declare the map like this:

unordered_map<CString, CString, CStringHash> map;
Sid S
  • 6,037
  • 2
  • 18
  • 24
  • This Hash function is flawed as it generates the Hash values based on the CString memory address and not on the CSting content, hence you will not achieve the intended result of accessing the correct element based on CString value. It only works if you use the same instance of CString to access the value in the unordered_map. – Tomasz Jul 06 '22 at 07:48
  • 1
    @Tomasz The hash template is set up to use an std::string, which is initialized from the pointer. The pointer is not used to generate the hash value. – Sid S Jul 07 '22 at 13:48