问题
G++使用unordered_map时候,编译报错:invalid use of incomplete type ‘struct std::hash<,。。。,放在G++6.5交叉编译环境是OK的,但是放在ubuntu14.04报错。
解决&代码
既然G++早期版本不能自动生成枚举类型的hash模板类,那么手动添加template<> struct std::hash<...。
添加如下代码 #if ....#endif区域代码,即可解决问题。
#include <unordered_map>
#include <utility>
#include <cstdint>
#include <iostream>
#include <functional>
namespace test{
enum COLOR{ WHITE, BLAC };
}
#if 0 // 如果没有这里,G++4.8.4和G++5.4.0会报错
namespace std {
template<>
struct hash<test::COLOR> {
typedef test::COLOR argument_type;
typedef size_t result_type;
result_type operator () (const argument_type& x) const {
using type = typename std::underlying_type<argument_type>::type;
return std::hash<type>()(static_cast<type>(x));
}
};
}
#endif
namespace test{
class mytest{
public:
std::unordered_map<COLOR, int> id_map_;
};
}
int main(){
test::mytest t;
return 0;
}
结论
发现是G++的问题,ubuntu14.04默认是g++4.8.4,ubuntu16.04是g++5.4。
参考:https://stackoverflow.com/questions/48294401/error-invalid-use-of-incomplete-type-struct-stdhash
ubuntu14.04
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ubuntu16.04
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
最后,ubuntu14.04下报错全部信息放在最后:
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_map:47,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/hashtable_policy.h: In instantiation of ‘struct std::__detail::_Hash_code_base<test::COLOR, std::pair<const test::COLOR, int>, std::__detail::_Select1st, std::hash<test::COLOR>, 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<test::COLOR, std::pair<const test::COLOR, int>, std::__detail::_Select1st, std::equal_to<test::COLOR>, std::hash<test::COLOR>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits<true, false, true> >’
/usr/include/c++/4.8/bits/hashtable.h:174:11: required from ‘class std::_Hashtable<test::COLOR, std::pair<const test::COLOR, int>, std::allocator<std::pair<const test::COLOR, int> >, std::__detail::_Select1st, std::equal_to<test::COLOR>, std::hash<test::COLOR>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >’
/usr/include/c++/4.8/bits/unordered_map.h:100:18: required from ‘class std::unordered_map<test::COLOR, int>’
unorderedmap.cpp:31:34: required from here
/usr/include/c++/4.8/bits/hashtable_policy.h:1070:12: error: invalid use of incomplete type ‘struct std::hash<test::COLOR>’
struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
^
In file included from /usr/include/c++/4.8/bits/basic_string.h:3033:0,
from /usr/include/c++/4.8/string:52,
from /usr/include/c++/4.8/stdexcept:39,
from /usr/include/c++/4.8/array:38,
from /usr/include/c++/4.8/tuple:39,
from /usr/include/c++/4.8/unordered_map:41,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<test::COLOR>’
struct hash;
^
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_map:47,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/hashtable_policy.h:1070:12: error: invalid use of incomplete type ‘struct std::hash<test::COLOR>’
struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
^
In file included from /usr/include/c++/4.8/bits/basic_string.h:3033:0,
from /usr/include/c++/4.8/string:52,
from /usr/include/c++/4.8/stdexcept:39,
from /usr/include/c++/4.8/array:38,
from /usr/include/c++/4.8/tuple:39,
from /usr/include/c++/4.8/unordered_map:41,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<test::COLOR>’
struct hash;
^
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_map:47,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/hashtable_policy.h:1082:53: error: invalid use of incomplete type ‘struct std::hash<test::COLOR>’
using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>;
^
In file included from /usr/include/c++/4.8/bits/basic_string.h:3033:0,
from /usr/include/c++/4.8/string:52,
from /usr/include/c++/4.8/stdexcept:39,
from /usr/include/c++/4.8/array:38,
from /usr/include/c++/4.8/tuple:39,
from /usr/include/c++/4.8/unordered_map:41,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<test::COLOR>’
struct hash;
^
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_map:47,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/hashtable_policy.h:1082:53: error: invalid use of incomplete type ‘struct std::hash<test::COLOR>’
using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>;
^
In file included from /usr/include/c++/4.8/bits/basic_string.h:3033:0,
from /usr/include/c++/4.8/string:52,
from /usr/include/c++/4.8/stdexcept:39,
from /usr/include/c++/4.8/array:38,
from /usr/include/c++/4.8/tuple:39,
from /usr/include/c++/4.8/unordered_map:41,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<test::COLOR>’
struct hash;
^
unorderedmap.cpp: In constructor ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type, const hasher&, const key_equal&, const allocator_type&) [with _Key = test::COLOR; _Tp = int; _Hash = std::hash<test::COLOR>; _Pred = std::equal_to<test::COLOR>; _Alloc = std::allocator<std::pair<const test::COLOR, int> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type = long unsigned int; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hasher = std::hash<test::COLOR>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_equal = std::equal_to<test::COLOR>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::allocator_type = std::allocator<std::pair<const test::COLOR, int> >]’:
unorderedmap.cpp:29:7: error: invalid use of incomplete type ‘std::unordered_map<test::COLOR, int>::hasher {aka struct std::hash<test::COLOR>}’
class mytest{
^
In file included from /usr/include/c++/4.8/bits/basic_string.h:3033:0,
from /usr/include/c++/4.8/string:52,
from /usr/include/c++/4.8/stdexcept:39,
from /usr/include/c++/4.8/array:38,
from /usr/include/c++/4.8/tuple:39,
from /usr/include/c++/4.8/unordered_map:41,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘std::unordered_map<test::COLOR, int>::hasher {aka struct std::hash<test::COLOR>}’
struct hash;
^
unorderedmap.cpp:29:7: note: when instantiating default argument for call to std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type, const hasher&, const key_equal&, const allocator_type&) [with _Key = test::COLOR; _Tp = int; _Hash = std::hash<test::COLOR>; _Pred = std::equal_to<test::COLOR>; _Alloc = std::allocator<std::pair<const test::COLOR, int> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type = long unsigned int; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hasher = std::hash<test::COLOR>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_equal = std::equal_to<test::COLOR>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::allocator_type = std::allocator<std::pair<const test::COLOR, int> >]
class mytest{
^
unorderedmap.cpp: In function ‘int main()’:
unorderedmap.cpp:36:18: note: synthesized method ‘test::mytest::mytest()’ first required here
test::mytest t ;
^
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_map:47,
from unorderedmap.cpp:1:
/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 = test::COLOR; _Value = std::pair<const test::COLOR, int>; _ExtractKey = std::__detail::_Select1st; _H1 = std::hash<test::COLOR>; _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 = test::COLOR; _Value = std::pair<const test::COLOR, int>; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<test::COLOR>; _H1 = std::hash<test::COLOR>; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _Traits = std::__detail::_Hashtable_traits<true, false, 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 = test::COLOR; _Value = std::pair<const test::COLOR, int>; _Alloc = std::allocator<std::pair<const test::COLOR, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<test::COLOR>; _H1 = std::hash<test::COLOR>; _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>::size_type = long unsigned int; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::allocator_type = std::allocator<std::pair<const test::COLOR, 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 = test::COLOR; _Value = std::pair<const test::COLOR, int>; _Alloc = std::allocator<std::pair<const test::COLOR, int> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<test::COLOR>; _H1 = std::hash<test::COLOR>; _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>::size_type = long unsigned int; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::key_equal = std::equal_to<test::COLOR>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>::allocator_type = std::allocator<std::pair<const test::COLOR, int> >]’
/usr/include/c++/4.8/bits/unordered_map.h:142:35: required from ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type, const hasher&, const key_equal&, const allocator_type&) [with _Key = test::COLOR; _Tp = int; _Hash = std::hash<test::COLOR>; _Pred = std::equal_to<test::COLOR>; _Alloc = std::allocator<std::pair<const test::COLOR, int> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type = long unsigned int; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hasher = std::hash<test::COLOR>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_equal = std::equal_to<test::COLOR>; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::allocator_type = std::allocator<std::pair<const test::COLOR, int> >]’
unorderedmap.cpp:29:7: required from here
/usr/include/c++/4.8/bits/hashtable_policy.h:1099:63: error: invalid use of incomplete type ‘struct std::hash<test::COLOR>’
: __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { }
^
In file included from /usr/include/c++/4.8/bits/basic_string.h:3033:0,
from /usr/include/c++/4.8/string:52,
from /usr/include/c++/4.8/stdexcept:39,
from /usr/include/c++/4.8/array:38,
from /usr/include/c++/4.8/tuple:39,
from /usr/include/c++/4.8/unordered_map:41,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<test::COLOR>’
struct hash;
^
In file included from /usr/include/c++/4.8/bits/hashtable.h:35:0,
from /usr/include/c++/4.8/unordered_map:47,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/hashtable_policy.h:1099:63: error: invalid use of incomplete type ‘struct std::hash<test::COLOR>’
: __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { }
^
In file included from /usr/include/c++/4.8/bits/basic_string.h:3033:0,
from /usr/include/c++/4.8/string:52,
from /usr/include/c++/4.8/stdexcept:39,
from /usr/include/c++/4.8/array:38,
from /usr/include/c++/4.8/tuple:39,
from /usr/include/c++/4.8/unordered_map:41,
from unorderedmap.cpp:1:
/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of ‘struct std::hash<test::COLOR>’
struct hash;