Workaround GCC 5.5 unordered_map bug - c++

This code works in GCC 6.1, but causes a compile error in GCC 5.5:
#include <memory>
#include <unordered_map>
#include <vector>
std::unordered_map<int, std::shared_ptr<std::vector<uint8_t>>> foo;
int main() {
foo.emplace(0, new std::vector<uint8_t>(1));
}
The error is below. Is there any way around this (I assume) bug?
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/x86_64-linux-gnu/bits/c++allocator.h:33:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/allocator.h:46,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:63,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/ext/new_allocator.h: In instantiation of 'void
__gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >; _Args = {int, std::vector<unsigned char, std::allocator<unsigned char> >*}; _Tp = std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >]':
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/alloc_traits.h:530:4: 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, std::shared_ptr<std::vector<unsigned char> > >; _Args = {int, std::vector<unsigned char, std::allocator<unsigned char> >*}; _Tp = std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<std::pair<const int, std::shared_ptr<std::vector<unsigned char> > > >]'
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/hashtable_policy.h:1955:37: required from 'std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type* std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&& ...) [with _Args = {int, std::vector<unsigned char, std::allocator<unsigned char> >*}; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >, false> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::__detail::_Hash_node<std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >, false>]'
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/hashtable.h:1517:77: required from 'std::pair<typename std::__detail::_Hashtable_base<_Key,
_Value, _ExtractKey, _Equal, _H1, _H2, _Hash, _Traits>::iterator, bool> std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1,
_H2, _Hash, _RehashPolicy, _Traits>::_M_emplace(std::true_type, _Args&& ...) [with _Args = {int, std::vector<unsigned char, std::allocator<unsigned char> >*}; _Key = int; _Value = std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >;
_Alloc = std::allocator<std::pair<const int, std::shared_ptr<std::vector<unsigned char> > > >; _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>; typename std::__detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, _H1,
_H2, _Hash, _Traits>::iterator = std::__detail::_Node_iterator<std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >, false, false>; std::true_type = std::integral_constant<bool, true>]'
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/hashtable.h:726:21: required from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey,
_Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::__ireturn_type std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2,
_Hash, _RehashPolicy, _Traits>::emplace(_Args&& ...) [with _Args = {int, std::vector<unsigned char, std::allocator<unsigned char> >*};
_Key = int; _Value = std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >; _Alloc = std::allocator<std::pair<const int, std::shared_ptr<std::vector<unsigned char> > > >; _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>::__ireturn_type = std::pair<std::__detail::_Node_iterator<std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >, false, false>, bool>]'
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/unordered_map.h:380:54: 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::__detail::__is_noexcept_hash<_Key, _Hash> > >::value, false, true> >::iterator, bool> std::unordered_map<_Key, _Tp, _Hash, _Pred,
_Alloc>::emplace(_Args&& ...) [with _Args = {int, std::vector<unsigned char, std::allocator<unsigned char> >*}; _Key = int; _Tp = std::shared_ptr<std::vector<unsigned char> >; _Hash = std::hash<int>;
_Pred = std::equal_to<int>; _Alloc = std::allocator<std::pair<const int, std::shared_ptr<std::vector<unsigned char> > > >; 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::__detail::__is_noexcept_hash<_Key, _Hash> > >::value, false, true> >::iterator = std::__detail::_Node_iterator<std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >, false, false>]'
<source>:8:47: required from here
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/ext/new_allocator.h:120:4: error: no matching function for call to 'std::pair<const int, std::shared_ptr<std::vector<unsigned char> > >::pair(int, std::vector<unsigned char>*)'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_algobase.h:64:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:62,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:206:9: note: candidate: template<class ... _Args1, long unsigned int ..._Indexes1, class ... _Args2, long unsigned int ..._Indexes2> std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>)
pair(tuple<_Args1...>&, tuple<_Args2...>&,
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:206:9: note: template argument deduction/substitution failed:
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/x86_64-linux-gnu/bits/c++allocator.h:33:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/allocator.h:46,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:63,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/ext/new_allocator.h:120:4: note: mismatched types 'std::tuple<_Elements ...>' and 'int'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_algobase.h:64:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:62,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:155:9: note: candidate: template<class ... _Args1, class ... _Args2> std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>)
pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:155:9: note: template argument deduction/substitution failed:
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/x86_64-linux-gnu/bits/c++allocator.h:33:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/allocator.h:46,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:63,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/ext/new_allocator.h:120:4: note: cannot convert 'std::forward<int>((* & __args#0))' (type 'int') to type 'std::piecewise_construct_t'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_algobase.h:64:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:62,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:150:12: note: candidate: template<class _U1, class _U2, class> constexpr std::pair<_T1, _T2>::pair(std::pair<_U1, _U2>&&)
constexpr pair(pair<_U1, _U2>&& __p)
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:150:12: note: template argument deduction/substitution failed:
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/x86_64-linux-gnu/bits/c++allocator.h:33:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/allocator.h:46,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:63,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/ext/new_allocator.h:120:4: note: mismatched types 'std::pair<_T1, _T2>' and 'int'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_algobase.h:64:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:62,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:144:12: note: candidate: template<class _U1, class _U2, class> constexpr std::pair<_T1, _T2>::pair(_U1&&, _U2&&)
constexpr pair(_U1&& __x, _U2&& __y)
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:144:12: note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:141:38: error: no type named 'type' in 'struct std::enable_if<false, void>'
template<class _U1, class _U2, class = typename
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:138:12: note: candidate: template<class _U2, class> constexpr std::pair<_T1,
_T2>::pair(const _T1&, _U2&&)
constexpr pair(const _T1& __x, _U2&& __y)
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:138:12: note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:136:27: error: no type named 'type' in 'struct std::enable_if<false, void>'
template<class _U2, class = typename
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:133:12: note: candidate: template<class _U1, class> constexpr std::pair<_T1,
_T2>::pair(_U1&&, const _T2&)
constexpr pair(_U1&& __x, const _T2& __y)
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:133:12: note: template argument deduction/substitution failed:
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/x86_64-linux-gnu/bits/c++allocator.h:33:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/allocator.h:46,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:63,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/ext/new_allocator.h:120:4: note: cannot convert 'std::forward<std::vector<unsigned char>*>((* &
__args#1))' (type 'std::vector<unsigned char>*') to type 'const std::shared_ptr<std::vector<unsigned char> >&'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_algobase.h:64:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:62,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:128:17: note: candidate: constexpr std::pair<_T1, _T2>::pair(std::pair<_T1,
_T2>&&) [with _T1 = const int; _T2 = std::shared_ptr<std::vector<unsigned char> >]
constexpr pair(pair&&) = default;
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:128:17: note: candidate expects 1 argument, 2 provided
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:127:17: note: candidate: constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = std::shared_ptr<std::vector<unsigned char> >]
constexpr pair(const pair&) = default;
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:127:17: note: candidate expects 1 argument, 2 provided
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:124:12: note: candidate: template<class _U1, class _U2, class> constexpr std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&)
constexpr pair(const pair<_U1, _U2>& __p)
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:124:12: note: template argument deduction/substitution failed:
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/x86_64-linux-gnu/bits/c++allocator.h:33:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/allocator.h:46,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:63,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/ext/new_allocator.h:120:4: note: mismatched types 'const std::pair<_T1, _T2>' and 'int'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
In file included from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_algobase.h:64:0,
from /opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/memory:62,
from <source>:1:
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:112:26: note: candidate: constexpr std::pair<_T1, _T2>::pair(const _T1&, const
_T2&) [with _T1 = const int; _T2 = std::shared_ptr<std::vector<unsigned char> >]
_GLIBCXX_CONSTEXPR pair(const _T1& __a, const _T2& __b)
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:112:26: note: no known conversion for argument 2 from 'std::vector<unsigned char>*' to 'const std::shared_ptr<std::vector<unsigned char> >&'
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:108:26: note: candidate: constexpr std::pair<_T1, _T2>::pair() [with _T1 = const int; _T2 = std::shared_ptr<std::vector<unsigned char> >]
_GLIBCXX_CONSTEXPR pair()
^
/opt/compiler-explorer/gcc-5.5.0/include/c++/5.5.0/bits/stl_pair.h:108:26: note: candidate expects 0 arguments, 2 provided
Compiler returned: 1

Use std::make_shared:
foo.emplace(0, std::make_shared<std::vector<uint8_t>>(1));
live example on wandbox.org

In C++11 the emplace method for map and unordered_map was cumbersome. By default it actually needs to be fed the construction parameters for the std::pair used for the insert method.
In c++17, I think, this is improved, so you can provide 2 arguments, and the second argument is only applied if the object is actually emplaced.
Meanwhile, back in C++11 you are forced to use the piecewise mechanism if you really want to insert objects on demand. C++11 emplace example
However, in your case, my main concern is that the new object is already built and might leak if it already has an index in the map, and does not get inserted. Using make_shared helps avoid that issue, at least!

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.

Custom std::set as value type to unordered_map

Let the code speak it:
auto SetCompare = [](const string& a, const string& b)
{
size_t L = a.length();
size_t R = b.length();
if (L == R) return (a < b);
return L < R;
};
using MySet = std::set<string, decltype(SetCompare)>;
unordered_map<string, MySet> Map;
The insertion or access won't work:
Map["abc"];
Map["xyz"].insert("mapped to xyz");
// Insert TO set works
MySet mySet(SetCompare); // HINT
mySet.insert("x");
mySet.insert("abc");
// But not to the map!
Map.insert({"pqr", mySet});
At the HINTed location, I pass SetCompare lambda (not just type) to MySet's constructor. The question is how to pass it to the "Value" type of unordered_map?
EDIT (Compiler errors):
GCC C++17
In file included from /usr/include/c++/7/set:60:0,
from main.cpp:10:
/usr/include/c++/7/bits/stl_tree.h: In instantiation of ‘std::_Rb_tree_key_compare<_Key_compare>::_Rb_tree_key_compare() [with _Key_compare = main()::<lambda(const string&, const string&)>]’:
/usr/include/c++/7/bits/stl_tree.h:688:4: required from ‘std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {char&&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const char; _T2 = std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> >]’
/usr/include/c++/7/tuple:1641:63: required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {char&&}; _Args2 = {}; _T1 = const char; _T2 = std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> >]’
/usr/include/c++/7/ext/new_allocator.h:136:4: required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >; _Args = {const std::piecewise_construct_t&, std::tuple<char&&>, std::tuple<>}; _Tp = std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >]’
/usr/include/c++/7/bits/alloc_traits.h:475:4: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >; _Args = {const std::piecewise_construct_t&, std::tuple<char&&>, std::tuple<>}; _Tp = std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > > >]’
/usr/include/c++/7/bits/hashtable_policy.h:2066:37: 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<char&&>, std::tuple<>}; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >, false> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::__detail::_Hash_node<std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >, false>]’
/usr/include/c++/7/bits/hashtable_policy.h:750:8: 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 = char; _Pair = std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >; _Alloc = std::allocator<std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > > >; _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; _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 = std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> >; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::key_type = char]’
/usr/include/c++/7/bits/unordered_map.h:977: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 = char; _Tp = std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> >; _Hash = std::hash<char>; _Pred = std::equal_to<char>; _Alloc = std::allocator<std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > > >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = char]’
<span class="error_line" onclick="ide.gotoLine('main.cpp',31)">main.cpp:31:7</span>: required from here
/usr/include/c++/7/bits/stl_tree.h:149:24: error: use of deleted function ‘main()::::()’
: _M_key_compare()
^
main.cpp:17:24: note: a lambda closure type has a deleted default constructor
auto SetCompare = [](const string& a, const string& b)
GCC C++17
In file included from /usr/include/c++/6/set:60:0,
from main.cpp:10:
/usr/include/c++/6/bits/stl_tree.h: In instantiation of ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Rb_tree_impl<_Key_compare, <anonymous> >::_Rb_tree_impl() [with _Key_compare = main()::<lambda(const string&, const string&)>; bool <anonymous> = false; _Key = std::basic_string<char>; _Val = std::basic_string<char>; _KeyOfValue = std::_Identity<std::basic_string<char> >; _Compare = main()::<lambda(const string&, const string&)>; _Alloc = std::allocator<std::basic_string<char> >]’:
/usr/include/c++/6/bits/stl_tree.h:821:18: required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Rb_tree() [with _Key = std::basic_string<char>; _Val = std::basic_string<char>; _KeyOfValue = std::_Identity<std::basic_string<char> >; _Compare = main()::<lambda(const string&, const string&)>; _Alloc = std::allocator<std::basic_string<char> >]’
/usr/include/c++/6/bits/stl_set.h:146:14: required from ‘std::set<_Key, _Compare, _Alloc>::set() [with _Key = std::basic_string<char>; _Compare = main()::<lambda(const string&, const string&)>; _Alloc = std::allocator<std::basic_string<char> >]’
/usr/include/c++/6/tuple:1590:70: required from ‘std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {char&&}; long unsigned int ..._Indexes1 = {0ul}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const char; _T2 = std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> >]’
/usr/include/c++/6/tuple:1579:63: required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {char&&}; _Args2 = {}; _T1 = const char; _T2 = std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> >]’
/usr/include/c++/6/ext/new_allocator.h:120:4: required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >; _Args = {const std::piecewise_construct_t&, std::tuple<char&&>, std::tuple<>}; _Tp = std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >]’
/usr/include/c++/6/bits/alloc_traits.h:475:4: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >; _Args = {const std::piecewise_construct_t&, std::tuple<char&&>, std::tuple<>}; _Tp = std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > > >]’
/usr/include/c++/6/bits/hashtable_policy.h:1953:37: 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<char&&>, std::tuple<>}; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >, false> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::__detail::_Hash_node<std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >, false>]’
/usr/include/c++/6/bits/hashtable_policy.h:620:8: 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 = char; _Pair = std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > >; _Alloc = std::allocator<std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > > >; _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; _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 = std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> >; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::key_type = char]’
/usr/include/c++/6/bits/unordered_map.h:908: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 = char; _Tp = std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> >; _Hash = std::hash<char>; _Pred = std::equal_to<char>; _Alloc = std::allocator<std::pair<const char, std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> > > >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = std::set<std::basic_string<char>, main()::<lambda(const string&, const string&)> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = char]’
<span class="error_line" onclick="ide.gotoLine('main.cpp',31)">main.cpp:31:7</span>: required from here
/usr/include/c++/6/bits/stl_tree.h:602:21: error: use of deleted function ‘main()::::()’
_M_node_count(0)
^
main.cpp:17:24: note: a lambda closure type has a deleted default constructor
auto SetCompare = [](const string& a, const string& b)
^
In file included from /usr/include/c++/6/set:60:0,
from main.cpp:10:
/usr/include/c++/6/bits/stl_tree.h:628:4: warning: ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Rb_tree_impl<_Key_compare, >::_M_initialize() [with _Key_compare = main()::; bool = false; _Key = std::basic_string; _Val = std::basic_string; _KeyOfValue = std::_Identity >; _Compare = main()::; _Alloc = std::allocator >]’ used but never defined
_M_initialize()
^~~~~~~~~~~~~
VC C++14/17
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\set(84,1): error C2280: 'main::<lambda_b1395bcc88464fd844969fa0764f137c>::<lambda_b1395bcc88464fd844969fa0764f137c>(void)': attempting to reference a deleted function
1>xx.cpp(923): message : see declaration of 'main::<lambda_b1395bcc88464fd844969fa0764f137c>::<lambda_b1395bcc88464fd844969fa0764f137c>'
1>xxx.cpp(923,20): message : 'main::<lambda_b1395bcc88464fd844969fa0764f137c>::<lambda_b1395bcc88464fd844969fa0764f137c>(void)': function was explicitly deleted
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\set(84): message : while compiling class template member function 'std::set<std::string,main::<lambda_b1395bcc88464fd844969fa0764f137c>,std::allocator<std::string>>::set(void)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.27.29110\include\tuple(975): message : see reference to function template instantiation 'std::set<std::string,main::<lambda_b1395bcc88464fd844969fa0764f137c>,std::allocator<std::string>>::set(void)' being compiled
1>xxx.cpp(937): message : see reference to class template instantiation 'std::set<std::string,main::<lambda_b1395bcc88464fd844969fa0764f137c>,std::allocator<std::string>>' being compiled
Lambdas are never default constructible before C++20 (see ClosureType::ClosureType() section on cppreference), so you must pass the SetCompare variable when constructing a MySet. Using -std=c++20/-std=c++2a on clang or GCC should work (demo), as well as /std:c++latest on MSVC.
To work around this limitation in earlier C++ versions define SetCompare as a functor type:
struct SetCompare
{
bool operator()(const string& a, const string& b)
{
size_t L = a.length();
size_t R = b.length();
if (L == R) return (a < b);
return L < R;
}
};
and use this type when defining MySet
using MySet = std::set<std::string, SetCompare>;

Compilation errors when trying to add data to a map in C++

I am having trouble adding elements to a map in c++.
class myClass{
private:
string s;
public:
myClass(const string &s_1);
};
myClass::myClass(const string &s_1){
s = s_1;
}
I need to create a map that can hold multiple instances of this class.
#include <map>
using std::map;
#include <utility>
using std::pair;
#include "myclass.h"
int main(){
map <string, pair<myClass, string>> myMap;
myClass m("something");
string identity = "identity";
string attribute = "attribute";
pair<myClass, string> p (m, attribute);
myMap[identity] = p;
}
On first glance this looked completely fine to me, but when I tried to compile it, I ran into a lot of issues. Haven't been able to figure out what it could be.
This is what I get when I try to compile, and it is not even half of it:
In file included from /usr/include/c++/7/bits/unique_ptr.h:37:0,
from /usr/include/c++/7/bits/locale_conv.h:41,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/regex:44,
from h.h:11,
from main.cpp:10:
/usr/include/c++/7/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 = {const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const std::basic_string<char>; _T2 = std::pair<myClass, std::basic_string<char> >]’:
/usr/include/c++/7/tuple:1641:63: required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; _Args2 = {}; _T1 = const std::basic_string<char>; _T2 = std::pair<myClass, std::basic_string<char> >]’
/usr/include/c++/7/ext/new_allocator.h:136:4: required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > >; _Args = {const std::piecewise_construct_t&, std::tuple<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >]’
/usr/include/c++/7/bits/alloc_traits.h:475:4: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > >; _Args = {const std::piecewise_construct_t&, std::tuple<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Tp = std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > > >]’
/usr/include/c++/7/bits/stl_tree.h:626:32: required from ‘void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_construct_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >*]’
/usr/include/c++/7/bits/stl_tree.h:643:21: required from ‘std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >*]’
/usr/include/c++/7/bits/stl_tree.h:2398:33: required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >]’
/usr/include/c++/7/bits/stl_map.h:493:8: required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::basic_string<char>; _Tp = std::pair<myClass, std::basic_string<char> >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::pair<myClass, std::basic_string<char> > > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::pair<myClass, std::basic_string<char> >; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::basic_string<char>]’
<span class="error_line" onclick="ide.gotoLine('main.cpp',22)">main.cpp:22:19</span>: required from here
/usr/include/c++/7/tuple:1652:70: error: no matching function for call to ‘std::pair >::pair()’
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:9:
/usr/include/c++/7/bits/stl_pair.h:436:9: note: candidate: template std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>)
pair(tuple<_Args1...>&, tuple<_Args2...>&,
^~~~
/usr/include/c++/7/bits/stl_pair.h:436:9: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/7/bits/unique_ptr.h:37:0,
from /usr/include/c++/7/bits/locale_conv.h:41,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/regex:44,
from h.h:11,
from main.cpp:10:
/usr/include/c++/7/tuple:1652:70: note: candidate expects 4 arguments, 0 provided
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:9:
/usr/include/c++/7/bits/stl_pair.h:375:9: note: candidate: template std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>)
pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
^~~~
/usr/include/c++/7/bits/stl_pair.h:375:9: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/7/bits/unique_ptr.h:37:0,
from /usr/include/c++/7/bits/locale_conv.h:41,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/regex:44,
from h.h:11,
from main.cpp:10:
/usr/include/c++/7/tuple:1652:70: note: candidate expects 3 arguments, 0 provided
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:9:
/usr/include/c++/7/bits/stl_pair.h:370:21: note: candidate: template::value) || (! std::is_same, _U2>::value)), myClass, std::basic_string >::_MoveConstructiblePair<_U1, _U2>() && (! std::_PCC<((! std::is_same::value) || (! std::is_same, _U2>::value)), myClass, std::basic_string >::_ImplicitlyMoveConvertiblePair<_U1, _U2>())), bool>::type > constexpr std::pair<_T1, _T2>::pair(std::pair<_U1, _U2>&&)
explicit constexpr pair(pair<_U1, _U2>&& __p)
^~~~
/usr/include/c++/7/bits/stl_pair.h:370:21: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/7/bits/unique_ptr.h:37:0,
from /usr/include/c++/7/bits/locale_conv.h:41,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/regex:44,
from h.h:11,
from main.cpp:10:
/usr/include/c++/7/tuple:1652:70: note: candidate expects 1 argument, 0 provided
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:9:
/usr/include/c++/7/bits/stl_pair.h:360:12: note: candidate: template::value) || (! std::is_same, _U2>::value)), myClass, std::basic_string >::_MoveConstructiblePair<_U1, _U2>() && std::_PCC<((! std::is_same::value) || (! std::is_same, _U2>::value)), myClass, std::basic_string >::_ImplicitlyMoveConvertiblePair<_U1, _U2>()), bool>::type > constexpr std::pair<_T1, _T2>::pair(std::pair<_U1, _U2>&&)
constexpr pair(pair<_U1, _U2>&& __p)
^~~~
/usr/include/c++/7/bits/stl_pair.h:360:12: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/7/bits/unique_ptr.h:37:0,
from /usr/include/c++/7/bits/locale_conv.h:41,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/regex:44,
from h.h:11,
from main.cpp:10:
/usr/include/c++/7/tuple:1652:70: note: candidate expects 1 argument, 0 provided
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:9:
/usr/include/c++/7/bits/stl_pair.h:350:21: note: candidate: template() && (! _ImplicitlyMoveConvertiblePair<_U1, _U2>())), bool>::type > constexpr std::pair<_T1, _T2>::pair(_U1&&, _U2&&)
explicit constexpr pair(_U1&& __x, _U2&& __y)
^~~~
/usr/include/c++/7/bits/stl_pair.h:350:21: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/7/bits/unique_ptr.h:37:0,
from /usr/include/c++/7/bits/locale_conv.h:41,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/regex:44,
from h.h:11,
from main.cpp:10:
/usr/include/c++/7/tuple:1652:70: note: candidate expects 2 arguments, 0 provided
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:9:
/usr/include/c++/7/bits/stl_pair.h:341:12: note: candidate: template() && _ImplicitlyMoveConvertiblePair<_U1, _U2>()), bool>::type > constexpr std::pair<_T1, _T2>::pair(_U1&&, _U2&&)
constexpr pair(_U1&& __x, _U2&& __y)
^~~~
/usr/include/c++/7/bits/stl_pair.h:341:12: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/7/bits/unique_ptr.h:37:0,
from /usr/include/c++/7/bits/locale_conv.h:41,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/regex:44,
from h.h:11,
from main.cpp:10:
/usr/include/c++/7/tuple:1652:70: note: candidate expects 2 arguments, 0 provided
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:9:
/usr/include/c++/7/bits/stl_pair.h:332:17: note: candidate: template(), bool>::type > std::pair<_T1, _T2>::pair(const _T1&, _U2&&)
explicit pair(const _T1& __x, _U2&& __y)
^~~~
/usr/include/c++/7/bits/stl_pair.h:332:17: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/7/bits/unique_ptr.h:37:0,
from /usr/include/c++/7/bits/locale_conv.h:41,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/regex:44,
from h.h:11,
from main.cpp:10:
/usr/include/c++/7/tuple:1652:70: note: candidate expects 2 arguments, 0 provided
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:9:
/usr/include/c++/7/bits/stl_pair.h:325:18: note: candidate: template(), bool>::type > constexpr std::pair<_T1, _T2>::pair(const _T1&, _U2&&)
constexpr pair(const _T1& __x, _U2&& __y)
^~~~
/usr/include/c++/7/bits/stl_pair.h:325:18: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/7/bits/unique_ptr.h:37:0,
from /usr/include/c++/7/bits/locale_conv.h:41,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/regex:44,
from h.h:11,
from main.cpp:10:
/usr/include/c++/7/tuple:1652:70: note: candidate expects 2 arguments, 0 provided
second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
^
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:9:
/usr/include/c++/7/bits/stl_pair.h:318:27: note: candidate: template, std::allocator > >(), bool>::type > constexpr std::pair<_T1, _T2>::pair(_U1&&, const _T2&)
explicit constexpr pair(_U1&& __x, const _T2& __y)
^~~~
/usr/include/c++/7/bits/stl_pair.h:318:27: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/7/bits/unique_ptr.h:37:0,
from /usr/include/c++/7/bits/locale_conv.h:41,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/regex:44,
from h.h:11,
from main.cpp:10:
The error is much longer than this
Your error is caused by the lack of default constructor for myClass.
map::operator[] must be able to default construct the maps value type (because it returns a reference to an entry in the map and so must be able to add values to the map if they are not already present).
The error is actually pretty clear, once you learn to read the error message
no matching function for call to ‘std::pair<>::pair()
The compiler hasn't been able to synthesize a default constructor for the pair, because of the lack of a default constructor for myClass.

issues with c++ unordered_map

I am preparing for coding interviews so I have been writing some c++ code on a website that has a nice grab bag of sample problems. When trying to compile my code on the website (not really sure what compiler version the website runs under the hood) I get a very peculiar unordered_map error. I have never run into this issue before, I did some research and find out the error was occurring due to how I was initializing my unordered_map. When initializing my unordered_map I use a c++ string as my key and value, for some reason the compiler is not liking that. The compiler keeps saying there is no hash function for "basic_string" but I am not using a basic_string, I am using a c++ string
#include <cstdlib>
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
void typeahead(const vector<string> &usernames, const vector<string> &queries) {
//error occurs right here at this initialization
//of HistoryHash
unordered_map<string, string> HistoryHash;
unordered_map<string, string>::iterator it;
string cur_query, cur_usrnm;
locale loc;
//------------------------------------
//rest of code irrelevant
Here is the complete/full error:
In file included from /usr/include/c++/4.7/unordered_map:45:0,
from user_file.cpp:6:
/usr/include/c++/4.7/bits/hashtable.h: In instantiation of 'void std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::insert(_InputIterator, _InputIterator) [with _InputIterator = std::basic_string<char>; _Key = std::basic_string<char>; _Value = std::pair<const std::basic_string<char>, std::basic_string<char> >; _Allocator = std::allocator<std::pair<const std::basic_string<char>, std::basic_string<char> > >; _ExtractKey = std::_Select1st<std::pair<const std::basic_string<char>, std::basic_string<char> > >; _Equal = std::equal_to<std::basic_string<char> >; _H1 = std::hash<std::basic_string<char> >; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; bool
__cache_hash_code = true; bool __constant_iterators = false; bool __unique_keys = true]':
user_file.cpp:56:52: required from here
/usr/include/c++/4.7/bits/hashtable.h:1410:61: error: no matching function for call to '__distance_fw(std::basic_string<char>&, std::basic_string<char>&)'
/usr/include/c++/4.7/bits/hashtable.h:1410:61: note: candidates are:
In file included from /usr/include/c++/4.7/bits/hashtable.h:36:0,
from /usr/include/c++/4.7/unordered_map:45,
from user_file.cpp:6:
/usr/include/c++/4.7/bits/hashtable_policy.h:44:5: note: template<class _Iterator> typename std::iterator_traits::difference_type std::__detail::__distance_fw(_Iterator, _Iterator, std::input_iterator_tag)
/usr/include/c++/4.7/bits/hashtable_policy.h:44:5: note:
template argument deduction/substitution failed:
In file included from /usr/include/c++/4.7/unordered_map:45:0,
from user_file.cpp:6:
/usr/include/c++/4.7/bits/hashtable.h:1410:61: note: candidate expects 3 arguments, 2 provided
In file included from /usr/include/c++/4.7/bits/hashtable.h:36:0,
from /usr/include/c++/4.7/unordered_map:45,
from user_file.cpp:6:
/usr/include/c++/4.7/bits/hashtable_policy.h:50:5: note: template<class _Iterator> typename std::iterator_traits::difference_type std::__detail::__distance_fw(_Iterator, _Iterator, std::forward_iterator_tag)
/usr/include/c++/4.7/bits/hashtable_policy.h:50:5: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/4.7/unordered_map:45:0,
from user_file.cpp:6:
/usr/include/c++/4.7/bits/hashtable.h:1410:61: note: candidate expects 3 arguments, 2 provided
In file included from /usr/include/c++/4.7/bits/hashtable.h:36:0,
from /usr/include/c++/4.7/unordered_map:45,
from user_file.cpp:6:
/usr/include/c++/4.7/bits/hashtable_policy.h:56:5: note: template<class _Iterator> typename std::iterator_traits::difference_type std::__detail::__distance_fw(_Iterator, _Iterator)
/usr/include/c++/4.7/bits/hashtable_policy.h:56:5: note: template argument deduction/substitution failed:
/usr/include/c++/4.7/bits/hashtable_policy.h: In substitution of 'template<class _Iterator> typename std::iterator_traits::difference_type std::__detail::__distance_fw(_Iterator, _Iterator) [with _Iterator = std::basic_string<char>]':
/usr/include/c++/4.7/bits/hashtable.h:1410:61: required from 'void std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::insert(_InputIterator, _InputIterator) [with _InputIterator = std::basic_string<char>; _Key = std::basic_string<char>; _Value = std::pair<const std::basic_string<char>, std::basic_string<char> >; _Allocator = std::allocator<std::pair<const std::basic_string<char>, std::basic_string<char> > >; _ExtractKey = std::_Select1st<std::pair<const std::basic_string<char>, std::basic_string<char> > >; _Equal = std::equal_to<std::basic_string<char> >; _H1 = std::hash<std::basic_string<char> >; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; bool __cache_hash_code = true; bool __constant_iterators = false; bool __unique_keys = true]'
user_file.cpp:56:52: required from here
/usr/include/c++/4.7/bits/hashtable_policy.h:56:5: error: no type named 'difference_type' in 'struct std::iterator_traits<std::basic_string<char> >'
In file included from /usr/include/c++/4.7/unordered_map:45:0,
from user_file.cpp:6:
/usr/include/c++/4.7/bits/hashtable.h: In instantiation of 'void std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::insert(_InputIterator, _InputIterator) [with _InputIterator = std::basic_string<char>; _Key = std::basic_string<char>; _Value = std::pair<const std::basic_string<char>, std::basic_string<char> >; _Allocator = std::allocator<std::pair<const std::basic_string<char>, std::basic_string<char> > >; _ExtractKey = std::_Select1st<std::pair<const std::basic_string<char>, std::basic_string<char> > >; _Equal = std::equal_to<std::basic_string<char> >; _H1 = std::hash<std::basic_string<char> >; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; bool __cache_hash_code = true; bool __constant_iterators = false; bool __unique_keys = true]':
user_file.cpp:56:52: required from here
/usr/include/c++/4.7/bits/hashtable.h:1418:2: error: no match for 'operator++' in '++__first'
/usr/include/c++/4.7/bits/hashtable.h:1419:4: error: no match for 'operator*' in '*__first'"
This line looks wrong:
HistoryHash.insert(cur_query, local_min);
There is no overload of std::unordered_map<std::string, std::string>::insert which takes two strings. Presumably you want
HistoryHash.insert(std::make_pair(cur_query, local_min));

How to use unordered_set that has elements that are vector of pair<int,int>

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.