解决方法 GCC 5.5 unordered_map 错误

Posted

技术标签:

【中文标题】解决方法 GCC 5.5 unordered_map 错误【英文标题】:Workaround GCC 5.5 unordered_map bug 【发布时间】:2018-04-27 09:34:25 【问题描述】:

此代码在 GCC 6.1 中有效,但在 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));

错误如下。有没有办法解决这个(我假设的)错误?

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

【问题讨论】:

为什么不用std::make_shared,靠搬家? 【参考方案1】:

使用std::make_shared:

foo.emplace(0, std::make_shared<std::vector<uint8_t>>(1));

live example on wandbox.org

【讨论】:

【参考方案2】:

在 C++11 中,map 和 unordered_map 的 emplace 方法很麻烦。默认情况下,它实际上需要为用于插入方法的 std::pair 提供构造参数。

我认为在 c++17 中,这一点得到了改进,因此您可以提供 2 个参数,并且仅在实际放置对象时才应用第二个参数。 同时,在 C++11 中,如果您真的想按需插入对象,则不得不使用分段机制。 C++11 emplace example

但是,在您的情况下,我主要担心的是新对象已经构建并且如果它已经在地图中有索引并且没有被插入,它可能会泄漏。至少,使用 make_shared 有助于避免这个问题!

【讨论】:

以上是关于解决方法 GCC 5.5 unordered_map 错误的主要内容,如果未能解决你的问题,请参考以下文章

[PHP] 再续 Laravel 5.5 接口 跨域问题 终极暴力解决办法

mysql 源码包安装

挑战练习5.5 堵住漏洞

[ubuntu]ubuntu安装指定版本GCC

mysql-server-5.5-win32:60 - Adding firewall rule for MySQL55 on port 3306. 求高手解释,具体解决方法

Linux下gcc编译依赖库可能出现的系列问题以及对应解决方法(以GDAL库为例)