I'd like to know if it is possible to use an object reference as a key in an unordered_map container in C++.
#include <unordered_map>
class Object {
int value;
};
struct object_hash {
inline size_t operator()(const Object& o) const { return 0; }
};
std::unordered_map<Object&, int, object_hash> map;
When trying to compile this simple snippet, I got some errors about methods redefinition:
Using clang with libc++
/usr/include/c++/v1/unordered_map:352:12: error: class member cannot be redeclared
size_t operator()(const _Cp& __x) const
Using gcc 4.6 with libstdc++
/usr/include/c++/4.6/bits/hashtable_policy.h:556:5: error: ‘std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type& std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::operator [with _Key = Object&, _Pair = std::pair, _Hashtable = std::_Hashtable, std::allocator >, std::_Select1st >, std::equal_to, object_hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true>, std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type = int]’ cannot be overloaded
/usr/include/c++/4.6/bits/hashtable_policy.h:537:5: error: with ‘std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type& std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::operator[](const _Key&) [with _Key = Object&, _Pair = std::pair, _Hashtable = std::_Hashtable, std::allocator >, std::_Select1st >, std::equal_to, object_hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true>, std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type = int]’
If I use an old gnu hash_map instead (__gnu_cxx::hash_map), I don't have this problem.
Is this some limitation imposed by the new standard, and if so, why?
Is there a way to workaround this limitation?
Unordered Map does not contain a hash function for a pair like it has for int, string, etc, So if we want to hash a pair then we have to explicitly provide it with a hash function that can hash a pair. unordered_map can takes upto 5 arguments: Key : Type of key values.
Note that while unordered_map::at() will throw if the key is not found, unordered_map::find() returns an invalid iterator ( unordered_map::end() ) - so you can avoid handling exceptions this way.
Just replace the int with something like unordered_map<int, int> . You're going to want to pass it with a const reference if you don't need to modify it. Don't use the const if you want to modify the original object that was used to call the function. Save this answer.
unordered_map is an associated container that stores elements formed by the combination of a key value and a mapped value. The key value is used to uniquely identify the element and the mapped value is the content associated with the key. Both key and value can be of any type predefined or user-defined.
The new standard defines std:reference_wrapper<T>
to work around this limitation.
It is implicitly convertible to a T&
so that it is transparent, and like references guarantee there is no null
state, however unlike references it can be re-seated.
More information in Using std::reference_wrapper
as key in std::map
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With