Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Trying to solve how to do a std::unordered_map<std::pair<..., ...>, ...>

39 views
Skip to first unread message

Aaron Gray

unread,
Oct 1, 2023, 4:59:45 PM10/1/23
to
I am trying to work out how to do a :-

class Type {
public:
std::string name;
....
};

std::unordered_map<std::pair<const Type *, const Type*>, bool, std::hash<Type>> subTypeMemorization;

Godbolt attempt xxample :-

https://godbolt.org/z/r4YrG841E

Many thanks in advance,

Aaron

Bonita Montero

unread,
Oct 2, 2023, 7:18:47 AM10/2/23
to
Am 01.10.2023 um 22:59 schrieb Aaron Gray:
> I am trying to work out how to do a :-
>
> class Type {
> public:
> std::string name;
> ....
> };
> std::unordered_map<std::pair<const Type *, const Type*>, bool, std::hash<Type>> subTypeMemorization;
> Godbolt attempt xxample :-
>
> https://godbolt.org/z/r4YrG841E

You must specialize the hasher yourself:

#include <string>
#include <utility>
#include <unordered_map>
#include <functional>

using namespace std;

struct Type
{
string name;
};

template<>
struct hash<pair<Type *, Type *>>
{
size_t operator ()( pair<Type *, Type *> const &key )
{
size_t hash = 0;
hash ^= key.first ? std::hash<string>()( key.first->name ) :
std::hash<void *>()( nullptr );
hash ^= key.second ? std::hash<string>()( key.first->name ) :
std::hash<void *>()( nullptr );
return hash;
}
};

unordered_map<pair<Type *, Type *>, bool> map;


Bonita Montero

unread,
Oct 2, 2023, 7:20:05 AM10/2/23
to
hash ^= key.second ? std::hash<string>()( key.second->name )

Aaron Gray

unread,
Oct 2, 2023, 8:10:19 AM10/2/23
to
On Monday, 2 October 2023 at 12:20:05 UTC+1, Bonita Montero wrote:
> > You must specialize the hasher yourself:

Bonita,

Great, I found another solution on Stack Overflow but will look into this one as it looks cleaner and more cannonical, thanks a lot.

https://stackoverflow.com/posts/32685618/revisions

Regards,

Aaron

Bonita Montero

unread,
Oct 2, 2023, 10:48:18 AM10/2/23
to
Am 02.10.2023 um 14:10 schrieb Aaron Gray:

> Bonita,
> Great, I found another solution on Stack Overflow but will look into this one as it looks cleaner and more cannonical, thanks a lot.
> https://stackoverflow.com/posts/32685618/revisions

The problem I have with that solution for you is that it will hash
the Type-pointer values of first and second and not the both strings
themselfes. This may lead to different hashes for identical strings
I'm hashing either the strings, or if either Pointer is nullptr, the
nullptr-hash.

Aaron Gray

unread,
Oct 2, 2023, 1:35:40 PM10/2/23
to
Hash functions are not my strong point but I can see you are covering the domain consistently in your code where the Stack Overflow example is almost random and probably overlapping input domains.

Thanks for pointing that out !

Aaron

Bonita Montero

unread,
Oct 3, 2023, 7:05:24 AM10/3/23
to
Am 02.10.2023 um 19:35 schrieb Aaron Gray:

> Thanks for pointing that out !

Maybe that should be the final solution:

template<>
struct hash<pair<Type*, Type*>>
{
size_t operator ()(pair<Type*, Type*> const& key)
{
size_t h = 0;
std::hash<string_view> hsv;
auto extend = [&]( auto, Type *pT ) { h ^= hsv( pT ?
string_view( pT->name.begin(), pT->name.end() ) : string_view( "" ) ); };
extend( false_type(), key.first );
extend( true_type(), key.second );
return h;
}
};

I use lambdas to save code. To force them to be inlined I make
them generic and call each instntiation only once. To instantiate
the lambda above twice I call them with different bool_constant<X>
types.

Aaron Gray

unread,
Oct 4, 2023, 4:26:33 PM10/4/23
to
I am not sure about this. I prefer your previous example.

Regards,

Aaron
0 new messages