Using unordered_map with custom value object in C++ [closed] - c++

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I'm trying to create an unordered_map where the key is of type char and the value is a pointer to my own custom class. Is this possible? Whenever I try compiling I get this among other errors:
$ g++ -std=c++0x -o spellchecker spellchecker.cpp -lstdc++
spellchecker.cpp:17:27: error: template argument 2 is invalid
spellchecker.cpp:17:27: error: template argument 5 is invalid
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;
class Node{
public:
Node();
~Node();
bool getletter;
bool iseofword;
char letter;
unordered_map<char, *Node> children; // line 17
};
I've tried:
unordered_map<char, Node> children; // line 17 (not pointer)
but I get this:
g++ -std=c++0x -o spellchecker spellchecker.cpp -lstdc++
In file included from /usr/include/c++/4.6/bits/stl_algobase.h:65:0,
from /usr/include/c++/4.6/bits/char_traits.h:41,
from /usr/include/c++/4.6/ios:41,
from /usr/include/c++/4.6/ostream:40,
from /usr/include/c++/4.6/iostream:40,
from spellchecker.cpp:1:
/usr/include/c++/4.6/bits/stl_pair.h: In instantiation of ‘std::pair<const char, Node>’:
/usr/include/c++/4.6/bits/stl_function.h:486:12: instantiated from ‘std::_Select1st<std::pair<const char, Node> >’
/usr/include/c++/4.6/bits/hashtable_policy.h:789:20: instantiated from ‘std::__detail::_Hash_code_base<char, std::pair<const char, Node>, std::_Select1st<std::pair<const char, Node> >, std::equal_to<char>, std::hash<char>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>’
/usr/include/c++/4.6/bits/hashtable.h:105:11: instantiated from ‘std::_Hashtable<char, std::pair<const char, Node>, std::allocator<std::pair<const char, Node> >, std::_Select1st<std::pair<const char, Node> >, std::equal_to<char>, std::hash<char>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true>’
/usr/include/c++/4.6/bits/unordered_map.h:44:11: instantiated from ‘std::__unordered_map<char, Node, std::hash<char>, std::equal_to<char>, std::allocator<std::pair<const char, Node> >, false>’
/usr/include/c++/4.6/bits/unordered_map.h:256:11: instantiated from ‘std::unordered_map<char, Node>’
spellchecker.cpp:17:28: instantiated from here
/usr/include/c++/4.6/bits/stl_pair.h:93:11: error: ‘std::pair<_T1, _T2>::second’ has incomplete type
spellchecker.cpp:8:7: error: forward declaration of ‘class Node’
spellchecker.cpp: In member function ‘int Trie::addword(std::string)’:
spellchecker.cpp:45:39: error: cannot convert ‘std::__detail::_Map_base<char, std::pair<const char, Node>, std::_Select1st<std::pair<const char, Node> >, true, std::_Hashtable<char, std::pair<const char, Node>, std::allocator<std::pair<const char, Node> >, std::_Select1st<std::pair<const char, Node> >, std::equal_to<char>, std::hash<char>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true> >::mapped_type {aka Node}’ to ‘Node*’ in assignment
spellchecker.cpp:52:39: error: cannot convert ‘std::__detail::_Map_base<char, std::pair<const char, Node>, std::_Select1st<std::pair<const char, Node> >, true, std::_Hashtable<char, std::pair<const char, Node>, std::allocator<std::pair<const char, Node> >, std::_Select1st<std::pair<const char, Node> >, std::equal_to<char>, std::hash<char>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true> >::mapped_type {aka Node}’ to ‘Node*’ in assignment
spellchecker.cpp:53:3: error: expected ‘;’ before ‘}’ token
spellchecker.cpp: In function ‘int main()’:
spellchecker.cpp:60:26: error: conversion from ‘Trie*’ to non-scalar type ‘Trie’ requested
In file included from /usr/include/c++/4.6/bits/hashtable.h:35:0,
from /usr/include/c++/4.6/unordered_map:45,
from spellchecker.cpp:3:
/usr/include/c++/4.6/bits/hashtable_policy.h: In member function ‘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 = char, _Pair = std::pair<const char, Node>, _Hashtable = std::_Hashtable<char, std::pair<const char, Node>, std::allocator<std::pair<const char, Node> >, std::_Select1st<std::pair<const char, Node> >, std::equal_to<char>, std::hash<char>, 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 = Node]’:
spellchecker.cpp:45:39: instantiated from here
/usr/include/c++/4.6/bits/hashtable_policy.h:549:24: error: ‘struct std::pair<const char, Node>’ has no member named ‘second’
/usr/include/c++/4.6/bits/hashtable_policy.h:550:26: error: ‘struct std::pair<const char, Node>’ has no member named ‘second’
In file included from /usr/include/c++/4.6/bits/stl_algobase.h:65:0,
from /usr/include/c++/4.6/bits/char_traits.h:41,
from /usr/include/c++/4.6/ios:41,
from /usr/include/c++/4.6/ostream:40,
from /usr/include/c++/4.6/iostream:40,
from spellchecker.cpp:1:
/usr/include/c++/4.6/bits/stl_pair.h: In constructor ‘std::pair<_T1, _T2>::pair(std::pair<_U1, _U2>&&) [with _U1 = char, _U2 = Node, _T1 = const char, _T2 = Node]’:
/usr/include/c++/4.6/bits/hashtable_policy.h:94:12: instantiated from ‘std::__detail::_Hash_node<_Value, false>::_Hash_node(_Args&& ...) [with _Args = {std::pair<char, Node>}, _Value = std::pair<const char, Node>]’
/usr/include/c++/4.6/ext/new_allocator.h:114:4: instantiated from ‘void __gnu_cxx::new_allocator<_Tp>::construct(__gnu_cxx::new_allocator<_Tp>::pointer, _Args&& ...) [with _Args = {std::pair<char, Node>}, _Tp = std::__detail::_Hash_node<std::pair<const char, Node>, false>, __gnu_cxx::new_allocator<_Tp>::pointer = std::__detail::_Hash_node<std::pair<const char, Node>, false>*]’
/usr/include/c++/4.6/bits/hashtable.h:485:6: instantiated from ‘std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Node* std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_M_allocate_node(_Args&& ...) [with _Args = {std::pair<char, Node>}, _Key = char, _Value = std::pair<const char, Node>, _Allocator = std::allocator<std::pair<const char, Node> >, _ExtractKey = std::_Select1st<std::pair<const char, Node> >, _Equal = std::equal_to<char>, _H1 = std::hash<char>, _H2 = std::__detail::_Mod_range_hashing, _Hash = std::__detail::_Default_ranged_hash, _RehashPolicy = std::__detail::_Prime_rehash_policy, bool __cache_hash_code = false, bool __constant_iterators = false, bool __unique_keys = true, std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Node = std::__detail::_Hash_node<std::pair<const char, Node>, false>]’
/usr/include/c++/4.6/bits/hashtable.h:928:62: instantiated from ‘std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::iterator std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_M_insert_bucket(_Arg&&, std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::size_type, typename std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Hash_code_type) [with _Arg = std::pair<char, Node>, _Key = char, _Value = std::pair<const char, Node>, _Allocator = std::allocator<std::pair<const char, Node> >, _ExtractKey = std::_Select1st<std::pair<const char, Node> >, _Equal = std::equal_to<char>, _H1 = std::hash<char>, _H2 = std::__detail::_Mod_range_hashing, _Hash = std::__detail::_Default_ranged_hash, _RehashPolicy = std::__detail::_Prime_rehash_policy, bool __cache_hash_code = false, bool __constant_iterators = false, bool __unique_keys = true, std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::iterator = std::__detail::_Hashtable_iterator<std::pair<const char, Node>, false, false>, std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::size_type = long unsigned int, typename std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Hash_code_type = long unsigned int]’
/usr/include/c++/4.6/bits/hashtable_policy.h:549:24: instantiated from ‘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 = char, _Pair = std::pair<const char, Node>, _Hashtable = std::_Hashtable<char, std::pair<const char, Node>, std::allocator<std::pair<const char, Node> >, std::_Select1st<std::pair<const char, Node> >, std::equal_to<char>, std::hash<char>, 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 = Node]’
spellchecker.cpp:45:39: instantiated from here
/usr/include/c++/4.6/bits/stl_pair.h:137:40: error: using invalid field ‘std::pair<_T1, _T2>::second

Your pointer notation is incorrect. *Node isn't valid. The * comes after the type, T* not *T.
unordered_map<char, Node*> children;

Related

Can an std::unordered_set store vector of pairs in c++? [duplicate]

I wanted to have something like
unordered_set<vector<pair<int,int>>> us;
but even without pair:
#include <vector>
#include <unordered_set>
using namespace std;
int main() {
unordered_set<vector<int>> um;
}
it fails:
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_set:47,
from prog.cpp:2:
/usr/include/c++/4.8/bits/hashtable_policy.h: In instantiation of ‘struct std::__detail::_Hash_code_base<std::vector<int>, std::vector<int>, std::__detail::_Identity, std::hash<std::vector<int> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>’:
/usr/include/c++/4.8/bits/hashtable_policy.h:1402:10: required from ‘struct std::__detail::_Hashtable_base<std::vector<int>, std::vector<int>, std::__detail::_Identity, std::equal_to<std::vector<int> >, std::hash<std::vector<int> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits<true, true, true> >’
/usr/include/c++/4.8/bits/hashtable.h:174:11: required from ‘class std::_Hashtable<std::vector<int>, std::vector<int>, std::allocator<std::vector<int> >, std::__detail::_Identity, std::equal_to<std::vector<int> >, std::hash<std::vector<int> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, true, true> >’
/usr/include/c++/4.8/bits/unordered_set.h:96:18: required from ‘class std::unordered_set<std::vector<int> >’
prog.cpp:7:32: required from here
/usr/include/c++/4.8/bits/hashtable_policy.h:1070:12: error: invalid use of incomplete type ‘struct std::hash<std::vector<int> >’
struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
^
In file included from /usr/include/c++/4.8/bits/stl_bvector.h:1134:0,
from /usr/include/c++/4.8/vector:65,
from prog.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<std::vector<int> >’
struct hash;
^
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_set:47,
from prog.cpp:2:
/usr/include/c++/4.8/bits/hashtable_policy.h:1070:12: error: invalid use of incomplete type ‘struct std::hash<std::vector<int> >’
struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
^
In file included from /usr/include/c++/4.8/bits/stl_bvector.h:1134:0,
from /usr/include/c++/4.8/vector:65,
from prog.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<std::vector<int> >’
struct hash;
^
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_set:47,
from prog.cpp:2:
/usr/include/c++/4.8/bits/hashtable_policy.h:1082:53: error: invalid use of incomplete type ‘struct std::hash<std::vector<int> >’
using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>;
^
In file included from /usr/include/c++/4.8/bits/stl_bvector.h:1134:0,
from /usr/include/c++/4.8/vector:65,
from prog.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<std::vector<int> >’
struct hash;
^
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_set:47,
from prog.cpp:2:
/usr/include/c++/4.8/bits/hashtable_policy.h:1082:53: error: invalid use of incomplete type ‘struct std::hash<std::vector<int> >’
using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>;
^
In file included from /usr/include/c++/4.8/bits/stl_bvector.h:1134:0,
from /usr/include/c++/4.8/vector:65,
from prog.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<std::vector<int> >’
struct hash;
^
prog.cpp: In constructor ‘std::unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(std::unordered_set<_Value, _Hash, _Pred, _Alloc>::size_type, const hasher&, const key_equal&, const allocator_type&) [with _Value = std::vector<int>; _Hash = std::hash<std::vector<int> >; _Pred = std::equal_to<std::vector<int> >; _Alloc = std::allocator<std::vector<int> >; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::size_type = unsigned int; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::hasher = std::hash<std::vector<int> >; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::key_equal = std::equal_to<std::vector<int> >; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::allocator_type = std::allocator<std::vector<int> >]’:
prog.cpp:7:32: error: invalid use of incomplete type ‘std::unordered_set<std::vector<int> >::hasher {aka struct std::hash<std::vector<int> >}’
unordered_set<vector<int>> um;
^
In file included from /usr/include/c++/4.8/bits/stl_bvector.h:1134:0,
from /usr/include/c++/4.8/vector:65,
from prog.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘std::unordered_set<std::vector<int> >::hasher {aka struct std::hash<std::vector<int> >}’
struct hash;
^
prog.cpp:7:32: note: when instantiating default argument for call to std::unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(std::unordered_set<_Value, _Hash, _Pred, _Alloc>::size_type, const hasher&, const key_equal&, const allocator_type&) [with _Value = std::vector<int>; _Hash = std::hash<std::vector<int> >; _Pred = std::equal_to<std::vector<int> >; _Alloc = std::allocator<std::vector<int> >; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::size_type = unsigned int; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::hasher = std::hash<std::vector<int> >; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::key_equal = std::equal_to<std::vector<int> >; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::allocator_type = std::allocator<std::vector<int> >]
unordered_set<vector<int>> um;
^
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_set:47,
from prog.cpp:2:
/usr/include/c++/4.8/bits/hashtable_policy.h: In instantiation of ‘std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, std::__detail::_Default_ranged_hash, true>::_Hash_code_base(const _ExtractKey&, const _H1&, const _H2&, const std::__detail::_Default_ranged_hash&) [with _Key = std::vector<int>; _Value = std::vector<int>; _ExtractKey = std::__detail::_Identity; _H1 = std::hash<std::vector<int> >; _H2 = std::__detail::_Mod_range_hashing]’:
/usr/include/c++/4.8/bits/hashtable_policy.h:1463:65: required from ‘std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, _Hash, _Traits>::_Hashtable_base(const _ExtractKey&, const _H1&, const _H2&, const _Hash&, const _Equal&) [with _Key = std::vector<int>; _Value = std::vector<int>; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to<std::vector<int> >; _H1 = std::hash<std::vector<int> >; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _Traits = std::__detail::_Hashtable_traits<true, true, true>]’
/usr/include/c++/4.8/bits/hashtable.h:828:24: required from ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::_Hashtable(std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::size_type, const _H1&, const _H2&, const _Hash&, const _Equal&, const _ExtractKey&, const allocator_type&) [with _Key = std::vector<int>; _Value = std::vector<int>; _Alloc = std::allocator<std::vector<int> >; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to<std::vector<int> >; _H1 = std::hash<std::vector<int> >; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, true, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::size_type = unsigned int; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::allocator_type = std::allocator<std::vector<int> >]’
/usr/include/c++/4.8/bits/hashtable.h:397:26: required from ‘std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::_Hashtable(std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::size_type, const _H1&, const key_equal&, const allocator_type&) [with _Key = std::vector<int>; _Value = std::vector<int>; _Alloc = std::allocator<std::vector<int> >; _ExtractKey = std::__detail::_Identity; _Equal = std::equal_to<std::vector<int> >; _H1 = std::hash<std::vector<int> >; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, true, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::size_type = unsigned int; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::key_equal = std::equal_to<std::vector<int> >; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::allocator_type = std::allocator<std::vector<int> >]’
/usr/include/c++/4.8/bits/unordered_set.h:136:35: required from ‘std::unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(std::unordered_set<_Value, _Hash, _Pred, _Alloc>::size_type, const hasher&, const key_equal&, const allocator_type&) [with _Value = std::vector<int>; _Hash = std::hash<std::vector<int> >; _Pred = std::equal_to<std::vector<int> >; _Alloc = std::allocator<std::vector<int> >; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::size_type = unsigned int; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::hasher = std::hash<std::vector<int> >; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::key_equal = std::equal_to<std::vector<int> >; std::unordered_set<_Value, _Hash, _Pred, _Alloc>::allocator_type = std::allocator<std::vector<int> >]’
prog.cpp:7:32: required from here
/usr/include/c++/4.8/bits/hashtable_policy.h:1099:63: error: invalid use of incomplete type ‘struct std::hash<std::vector<int> >’
: __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { }
^
In file included from /usr/include/c++/4.8/bits/stl_bvector.h:1134:0,
from /usr/include/c++/4.8/vector:65,
from prog.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<std::vector<int> >’
struct hash;
^
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_set:47,
from prog.cpp:2:
/usr/include/c++/4.8/bits/hashtable_policy.h:1099:63: error: invalid use of incomplete type ‘struct std::hash<std::vector<int> >’
: __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { }
^
In file included from /usr/include/c++/4.8/bits/stl_bvector.h:1134:0,
from /usr/include/c++/4.8/vector:65,
from prog.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<std::vector<int> >’
struct hash;
^
http://ideone.com/wusr5V
You could implement it like this, based on boost::hash_combine for a sensible calculation of hashes:
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <unordered_set>
namespace
{
// a little helper that should IMHO be standardized
template<typename T>
std::size_t make_hash(const T& v)
{
return std::hash<T>()(v);
}
// adapted from boost::hash_combine
void hash_combine(std::size_t& h, const std::size_t& v)
{
h ^= v + 0x9e3779b9 + (h << 6) + (h >> 2);
}
// hash any container
template<typename T>
struct hash_container
{
size_t operator()(const T& v) const
{
size_t h=0;
for( const auto& e : v ) {
hash_combine(h, make_hash(e));
}
return h;
}
};
}
namespace std
{
// support for pair<T,U> if T and U can be hashed
template<typename T, typename U>
struct hash<pair<T, U>>
{
size_t operator()(const pair<T,U>& v) const
{
size_t h=make_hash(v.first);
hash_combine(h, make_hash(v.second));
return h;
}
};
// support for vector<T> if T is hashable
// (the T... is a required trick if the vector has a non-standard allocator)
template<typename... T>
struct hash<vector<T...>> : hash_container<vector<T...>> {};
// the same for map<T,U> if T and U are hashable
template<typename... T>
struct hash<map<T...>> : hash_container<map<T...>> {};
// simply add more containers as needed
}
int main()
{
std::unordered_set<std::vector<std::pair<int,int>>> us;
us.insert(std::vector<std::pair<int,int>>{{{42,0},{17,64}}});
std::cout << us.size() << std::endl;
std::cout << us.begin()->size() << std::endl;
std::cout << us.begin()->begin()->first << std::endl;
std::unordered_set<std::map<int,int>> usm;
std::map<int,int> m{{42,0},{17,64}};
usm.insert(m);
}
Live example
Note that there was a problem when combining Clang with libstdc++ which might affect you when specializing std::hash. It has been fixed with GCC 4.8.2, but it is still visible on Coliru. If this is a problem in your case, you could disable the warning with -Wno-mismatched-tags and Clang will no longer complain.
You should write a hasher for your types, for example:
class MyHash
{
public:
std::size_t operator()(const vector<pair<int,int>> &v) const
{
std::size_t x = 0;
for (auto &i : v)
x ^= std::hash<int>()(i.first) ^ std::hash<int>()(i.second);
return x;
}
};
int main()
{
unordered_set<vector<pair<int,int>>, MyHash> um;
}
Note: The hash function that I wrote is just an example, it can be replaced with another and better one.

Emplacing an object from its own static member func yields "constructor declared private error"

In the following snippet I try to instantiate objects from within a static member function of the object (factory method). I'm putting the newly created object into an unordered_map via ::emplace(), however this fails because I want to have the constructor private (in the real context another static member function calls Place() which is also private there).
Snippet:
#include <unordered_map>
class Minimal
{
public:
static Minimal& Place(int id) {
static std::unordered_map<int, Minimal> collection;
auto it = collection.find(id);
if (it == end(collection)) {
it = collection.emplace(id, id).first;
}
return (*it).second;
}
private:
int id_;
Minimal(int id) : id_(id) {};
};
int main()
{
Minimal::Place(2);
}
Compiler Error (gcc 11.2):
In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/x86_64-linux-gnu/bits/c++allocator.h:33,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/allocator.h:46,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/unordered_map:40,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const int, Minimal>; _Args = {int&, int&}; _Tp = std::__detail::_Hash_node<std::pair<const int, Minimal>, false>]':
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/alloc_traits.h:512:17: required from 'static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const int, Minimal>; _Args = {int&, int&}; _Tp = std::__detail::_Hash_node<std::pair<const int, Minimal>, false>; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<std::__detail::_Hash_node<std::pair<const int, Minimal>, false> >]'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/hashtable_policy.h:1875:36: required from 'std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type* std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&& ...) [with _Args = {int&, int&}; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const int, Minimal>, false> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_ptr = std::allocator<std::__detail::_Hash_node<std::pair<const int, Minimal>, false> >::value_type*]'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/hashtable.h:289:35: required from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_Scoped_node::_Scoped_node(std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__hashtable_alloc*, _Args&& ...) [with _Args = {int&, int&}; _Key = int; _Value = std::pair<const int, Minimal>; _Alloc = std::allocator<std::pair<const int, Minimal> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<int>; _Hash = std::hash<int>; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__hashtable_alloc = std::_Hashtable<int, std::pair<const int, Minimal>, std::allocator<std::pair<const int, Minimal> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::__hashtable_alloc]'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/hashtable.h:1945:15: required from 'std::pair<typename std::__detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::iterator, bool> std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_M_emplace(std::true_type, _Args&& ...) [with _Args = {int&, int&}; _Key = int; _Value = std::pair<const int, Minimal>; _Alloc = std::allocator<std::pair<const int, Minimal> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<int>; _Hash = std::hash<int>; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; typename std::__detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::iterator = std::__detail::_Insert_base<int, std::pair<const int, Minimal>, std::allocator<std::pair<const int, Minimal> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::iterator; typename _Traits::__constant_iterators = std::__detail::_Hashtable_traits<false, false, true>::__constant_iterators; std::true_type = std::integral_constant<bool, true>]'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/hashtable.h:898:21: required from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__ireturn_type std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::emplace(_Args&& ...) [with _Args = {int&, int&}; _Key = int; _Value = std::pair<const int, Minimal>; _Alloc = std::allocator<std::pair<const int, Minimal> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<int>; _Hash = std::hash<int>; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__ireturn_type = std::_Hashtable<int, std::pair<const int, Minimal>, std::allocator<std::pair<const int, Minimal> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::__ireturn_type]'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/unordered_map.h:389:23: required from 'std::pair<typename std::_Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc, std::__detail::_Select1st, _Pred, _Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<std::__not_<std::__and_<std::__is_fast_hash<_Hash>, std::__is_nothrow_invocable<const _Hash&, const _Key&> > >::value, false, true> >::iterator, bool> std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::emplace(_Args&& ...) [with _Args = {int&, int&}; _Key = int; _Tp = Minimal; _Hash = std::hash<int>; _Pred = std::equal_to<int>; _Alloc = std::allocator<std::pair<const int, Minimal> >; typename std::_Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc, std::__detail::_Select1st, _Pred, _Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<std::__not_<std::__and_<std::__is_fast_hash<_Hash>, std::__is_nothrow_invocable<const _Hash&, const _Key&> > >::value, false, true> >::iterator = std::__detail::_Insert_base<int, std::pair<const int, Minimal>, std::allocator<std::pair<const int, Minimal> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::iterator]'
<source>:12:36: required from here
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ext/new_allocator.h:162:11: error: 'Minimal::Minimal(int)' is private within this context
162 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:19:5: note: declared private here
19 | Minimal(int id) : id_(id) {};
| ^~~~~~~
I understand this error which is due to the allocator of emplace() not being called within the scope of the object, therefore it has no access to the private constructor. But how to I get around it?
Don't make the constructor private. Instead make it difficult to call from outside of the class.
E.g. you can add private: struct PrivateTag {};, and add PrivateTag & as a parameter for the constructor.
(Note lvalue reference. Passing the tag by value or by a const reference doesn't work, since it allows anyone to just pass {}.)

user defined classes in unordered map

I'm using C++17, MSYS2 MinGW64, OpenGL, stb_image on VScode on Windows. In my code below, I'm trying to recursively search a specific directory for every .png file to load textures (using the Texture object that takes in a std::string parameter). When I run my code, I get these errors:
C:/msys64/mingw64/include/c++/10.2.0/tuple: In instantiation of 'std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {int&&}; long long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long long unsigned int ..._Indexes2 = {}; _T1 = const int; _T2 = Texture]':
C:/msys64/mingw64/include/c++/10.2.0/tuple:1678:63: required from 'std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {int&&}; _Args2 = {}; _T1 = const int; _T2 = Texture]'
C:/msys64/mingw64/include/c++/10.2.0/ext/new_allocator.h:150:4: required from 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const int, Texture>; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Tp = std::__detail::_Hash_node<std::pair<const int, Texture>, false>]'
C:/msys64/mingw64/include/c++/10.2.0/bits/alloc_traits.h:512:17: required from 'static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const int, Texture>; _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Tp = std::__detail::_Hash_node<std::pair<const int, Texture>, false>; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<std::__detail::_Hash_node<std::pair<const int, Texture>, false> >]'
C:/msys64/mingw64/include/c++/10.2.0/bits/hashtable_policy.h:2037:36: required from 'std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type* std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&& ...) [with _Args =
{const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const int, Texture>, false> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::allocator<std::__detail::_Hash_node<std::pair<const int, Texture>, false> >::value_type]'
C:/msys64/mingw64/include/c++/10.2.0/bits/hashtable.h:272:35: required from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::_Scoped_node::_Scoped_node(std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__hashtable_alloc*, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Value = std::pair<const int, Texture>; _Alloc = std::allocator<std::pair<const int, Texture> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<int>; _H1 = std::hash<int>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__hashtable_alloc = std::_Hashtable<int, std::pair<const int, Texture>, std::allocator<std::pair<const int, Texture> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::__hashtable_alloc]'
C:/msys64/mingw64/include/c++/10.2.0/bits/hashtable_policy.h:739:42: required from 'std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::mapped_type& std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::operator[](std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::key_type&&) [with _Key = int; _Pair = std::pair<const int, Texture>; _Alloc = std::allocator<std::pair<const int, Texture> >; _Equal = std::equal_to<int>; _H1 = std::hash<int>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::mapped_type = Texture; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::key_type = int]'
C:/msys64/mingw64/include/c++/10.2.0/bits/unordered_map.h:988:20: required from 'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type& std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type&&) [with _Key = int; _Tp = Texture; _Hash = std::hash<int>; _Pred = std::equal_to<int>; _Alloc = std::allocator<std::pair<const int, Texture> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = Texture; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = int]'
src/GameUI.cpp:32:50: required from here
C:/msys64/mingw64/include/c++/10.2.0/tuple:1689:70: error: no matching function for call to 'Texture::Texture()'
1689 | second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
How can I resolve this?
Also, are there any corrections or suggestions that could be made to improve my code (especially the map.emplace bit)?
Code:
#include "Texture.h"
#include <string>
#include <unordered_map>
#include <filesystem>
#include <iostream>
int main() {
std::unordered_map<int, Texture> map;
std::string path {"resources\\"};
std::string ext {".png"};
size_t count {};
for (auto &p : std::filesystem::recursive_directory_iterator(path)) {
if (p.path().extension() == ext) {
map.emplace(count, Texture{p.path().string()}); // Is this the most efficient way?
std::cout << p.path().string() << std::endl;
}
else if (!p.is_directory())
count++;
}
Texture test = map[7]; // Line 32 in GameUI.cpp
return 0;
}
Texture test = map[7];
map[7] returns a reference on a Texture, or default-constructs it if doesn't exist yet. If Texture doesn't have a default constructor, you get this error.
Try using map::at() instead, which throw an exception if map[7] doesn't exist. Or map::find() if you don't want exceptions. Or, well, just define Texture::Texture()...
map.emplace(count, Texture{p.path().string()}); // Is this the most efficient way?
I guess map.emplace(count, p.path().string()) should be enough, here?

Hashing an unordered_map of pair<pair<int,int>,pair<int,int>>

I have defined the following types
typedef pair<int,int> point ;
typedef pair<int,int> fraction ;
typedef pair<fraction,fraction> line ;
with a custom hash function as follows -
struct hash_pair {
template <class T1, class T2>
size_t operator() (const pair<T1, T2> &pair) const
{
return hash<T1>()(pair.first) ^ hash<T2>()(pair.second);
}
};
I've declared two maps as follows -
unordered_map<point, int, hash_pair> points ;
unordered_map<line, int, hash_pair> lines ;
I also have two variables point p and line l that I assign appropriately. When I performed points.find(p), it works properly. However, when I use lines.find(l), I'm obtaining endless lines of errors as follows -
solution.cpp: In instantiation of 'size_t hash_pair::operator()(const std::pair<_T1, _T2>&) const [with T1 = std::pair<int, int>; T2 = std::pair<int, int>; size_t = long unsigned int]':
/usr/include/c++/9.2.0/bits/hashtable_policy.h:1384:16: required from 'std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, std::__detail::_Default_ranged_hash, true>::__hash_code std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, std::__detail::_Default_ranged_hash, true>::_M_hash_code(const _Key&) const [with _Key = std::pair<std::pair<int, int>, std::pair<int, int> >; _Value = std::pair<const std::pair<std::pair<int, int>, std::pair<int, int> >, int>; _ExtractKey = std::__detail::_Select1st; _H1 = hash_pair; _H2 = std::__detail::_Mod_range_hashing; std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, std::__detail::_Default_ranged_hash, true>::__hash_code = long unsigned int]'
/usr/include/c++/9.2.0/bits/hashtable.h:1417:19: required from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::iterator std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::find(const key_type&) [with _Key = std::pair<std::pair<int, int>, std::pair<int, int> >; _Value = std::pair<const std::pair<std::pair<int, int>, std::pair<int, int> >, int>; _Alloc = std::allocator<std::pair<const std::pair<std::pair<int, int>, std::pair<int, int> >, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<std::pair<std::pair<int, int>, std::pair<int, int> > >; _H1 = hash_pair; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::iterator = std::__detail::_Node_iterator<std::pair<const std::pair<std::pair<int, int>, std::pair<int, int> >, int>, false, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::key_type = std::pair<std::pair<int, int>, std::pair<int, int> >]'
/usr/include/c++/9.2.0/bits/unordered_map.h:921:29: required from 'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::iterator std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::find(const key_type&) [with _Key = std::pair<std::pair<int, int>, std::pair<int, int> >; _Tp = int; _Hash = hash_pair; _Pred = std::equal_to<std::pair<std::pair<int, int>, std::pair<int, int> > >; _Alloc = std::allocator<std::pair<const std::pair<std::pair<int, int>, std::pair<int, int> >, int> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::iterator = std::__detail::_Node_iterator<std::pair<const std::pair<std::pair<int, int>, std::pair<int, int> >, int>, false, true>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = std::pair<std::pair<int, int>, std::pair<int, int> >]'
solution.cpp:105:30: required from here
solution.cpp:11:16: error: use of deleted function 'std::hash<std::pair<int, int> >::hash()'
15 | return hash<T1>()(pair.first) ^ hash<T2>()(pair.second);
|
There are two errors marked on lines.find(l), and another one on return hash<T1>()(pair.first) ^ hash<T2>()(pair.second);
Can anyone please help me out how I perform regular use of unordered_map on the pair<pair<int,int>,pair<int,int>> ? Thanks!
The simplest way to deal with nested pairs would be to recurse and provide an overload that exits when the argument is not a pair. For example:
struct hash_pair {
template <class T1, class T2>
size_t operator() (const pair<T1, T2> &pair) const
{
return (*this)(pair.first) ^ (*this)(pair.second);
}
template <class T>
size_t operator() (const T &v) const
{
return hash<T>()(v);
}
};
(Of course, simple xor is not a great way to hash a pair.)

Partial std::hash specialization for const and non-const types

I am having trouble with some code doing partial specialization of std::hash for one of my classes. Here's a self contained example.
EDIT: Thanks Piotr, I changed the code to include the fixes but the error remains.
#include <functional>
#include <string>
#include <unordered_set>
#include <unordered_map>
class Base
{
public:
template <class T>
using const_pset = std::unordered_set<const T *, std::hash <T *>, std::equal_to <T *> >;
template <class T, class U>
using const_pmap = std::unordered_map<const T *, U, std::hash <T *>, std::equal_to <T *> >;
};
class A : public Base
{
public:
std::size_t hash () const
{
std::hash<std::string> hashfn;
return hashfn (str);
}
bool operator== (const A &a) const { return str == a.str; }
std::string str;
};
namespace std
{
template <>
struct hash <A *>
{
typedef A argument_type;
typedef std::size_t result_type;
result_type operator () (const argument_type *op) const
{
return op->hash ();
}
};
template <>
struct hash <const A *>
{
typedef A argument_type;
typedef std::size_t result_type;
result_type operator () (const argument_type *op) const
{
return op->hash ();
}
};
};
extern const A* get_a ();
typedef Base::const_pmap<A, Base::const_pset<A> > mapA;
int
work (mapA &mapa)
{
const A *a = get_a ();
mapa[a];
return 0;
}
If you compile it with (g++ 4.9.0):
$ g++ -std=gnu++11 -Wall -c test.cc 2>&1 | head -n 50
In file included from /tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/hashtable.h:35:0,
from /tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/unordered_set:47,
from test.cc:3:
/tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/hashtable_policy.h: In instantiation of 'static bool std::__detail::_Equal_helper<_Key, _Value, _ExtractKey, _Equal, _HashCodeType, true>::_S_equals(const _Equal&, const _ExtractKey&, const _Key&, _HashCodeType, std::__detail::_Hash_node<_Value, true>*) [with _Key = const A*; _Value = std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<A*>; _HashCodeType = long unsigned int]':
/tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/hashtable_policy.h:1707:23: required from 'bool std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, _Hash, _Traits>::_M_equals(const _Key&, std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, _Hash, _Traits>::__hash_code, std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, _Hash, _Traits>::__node_type*) const [with _Key = const A*; _Value = std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<A*>; _H1 = std::hash<A*>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _Traits = std::__detail::_Hashtable_traits<true, false, true>; std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, _Hash, _Traits>::__hash_code = long unsigned int; std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, _Hash, _Traits>::__node_type = std::__detail::_Hash_node<std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > >, true>]'
/tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/hashtable.h:1391:4: required from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__node_base* std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::_M_find_before_node(std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::size_type, const key_type&, std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__hash_code) const [with _Key = const A*; _Value = std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > >; _Alloc = std::allocator<std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > > >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<A*>; _H1 = std::hash<A*>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__node_base = std::__detail::_Hash_node_base; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::size_type = long unsigned int; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::key_type = const A*; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__hash_code = long unsigned int]'
/tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/hashtable.h:590:65: required from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__node_type* std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::_M_find_node(std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::size_type, const key_type&, std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__hash_code) const [with _Key = const A*; _Value = std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > >; _Alloc = std::allocator<std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > > >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<A*>; _H1 = std::hash<A*>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__node_type = std::__detail::_Hash_node<std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > >, true>; typename _Traits::__hash_cached = std::integral_constant<bool, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::size_type = long unsigned int; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::key_type = const A*; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__hash_code = long unsigned int]'
/tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/hashtable_policy.h:597:60: required from 'std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::mapped_type& std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::operator[](const key_type&) [with _Key = const A*; _Pair = std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > >; _Alloc = std::allocator<std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > > >; _Equal = std::equal_to<A*>; _H1 = std::hash<A*>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::mapped_type = std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> >; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::key_type = const A*]'
/tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/unordered_map.h:627:20: required from 'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type& std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type&) [with _Key = const A*; _Tp = std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> >; _Hash = std::hash<A*>; _Pred = std::equal_to<A*>; _Alloc = std::allocator<std::pair<const A* const, std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> > > >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = std::unordered_set<const A*, std::hash<A*>, std::equal_to<A*>, std::allocator<const A*> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = const A*]'
test.cc:61:9: required from here
/tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/hashtable_policy.h:1326:74: error: invalid conversion from 'const A*' to 'A*' [-fpermissive]
{ return __c == __n->_M_hash_code && __eq(__k, __extract(__n->_M_v())); }
^
In file included from /tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/functional:49:0,
from test.cc:1:
/tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/stl_function.h:339:7: note: initializing argument 1 of 'bool std::equal_to<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = A*]'
operator()(const _Tp& __x, const _Tp& __y) const
^
In file included from /tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/hashtable.h:35:0,
from /tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/unordered_set:47,
from test.cc:3:
/tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/hashtable_policy.h:1326:74: error: invalid conversion from 'type {aka const A*}' to 'A*' [-fpermissive]
{ return __c == __n->_M_hash_code && __eq(__k, __extract(__n->_M_v())); }
^
In file included from /tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/functional:49:0,
from test.cc:1:
/tools/oss/packages/x86_64-rhel5/gcc/4.9.0/include/c++/4.9.0/bits/stl_function.h:339:7: note: initializing argument 2 of 'bool std::equal_to<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = A*]'
operator()(const _Tp& __x, const _Tp& __y) const
^
I can't understand why I am getting: error: invalid conversion from 'const A*' to 'A*' [-fpermissive].
Any suggestions on improving the code? It seems strange to have to specialize hash for both A and const A given the template body is the same.
Apologies, just noticed that I need to add const to the std::hash and std::equal_to parameters as well:
template <class T, class U>
using const_pmap = std::unordered_map<const T *, U, std::hash <const T *>, std::equal_to <const T *> >
I am still happy to receive answers about improving the code.
You wrote your specialization for A, but you use it with A*, so you need :
namespace std
{
template <>
struct hash<A*>
{
typedef const A* argument_type;
typedef std::size_t result_type;
result_type operator () (const argument_type op) const
{
return op->hash ();
}
};
}
And your std::unordered_map is for const A* :
template <class T, class U>
using const_pmap = std::unordered_map<const T *, U, std::hash <T *>, std::equal_to <const T *> >;
But since equal_to calls operator== by default, you actually don't need it (unless you want to specialize it, too) :
class Base
{
public:
template <class T>
using const_pset = std::unordered_set<const T *, std::hash <T *> >;
template <class T, class U>
using const_pmap = std::unordered_map<const T *, U, std::hash <T *>>;
};
Compiled Demo