Why can't I replace std::map with std::unordered_map

余生长醉 提交于 2019-11-27 07:39:34

问题


This question might be a bit sketchy because I do not have the code available at home, but I know this thing otherwise will bug me the whole weekend.

When I tried to update some code to C++11 I began replacing some std::map with std::unordered_map. The code only used std::map::find() to access a specific element in the map, so I figured the replacement should be easy. The returned iterator was stored in an auto-typed variable (auto res = map.find( x ), so the typing should check out fine. However when accessing the stored element using res->second.do_stuff() I got a compiler error, telling me, that struct std::pair<char, B> does not have a member second. Now this really confused me, but unfortunately I did not have time to investigate further.

Maybe this is enough information, so someone can give me a hint on this weird compiler error. Or is my understanding that std::map and std::unordered_map should have the same interface except for the parts which need an ordering, not correct?

EDIT:

As promised here some more analysis on the problem. Most likely this will allow someone to help me out better now. As I guessed from the hints in the comments, this was not really caused by the point where I accessed the elements in the map, but by some other part of the code. The reason I found was, that I used the map within Class X to store pointers to other elements of Class X (a kind of tree structure). However this seems to work for std::map but not for std::unordered_map. Here is some very simple code that exhibits the problem:

#include <stdint.h>
#include <unordered_map>
#include <map>

class Test {
  std::map<uint32_t, Test> m_map1; // Works
  std::unordered_map<uint32_t, Test> m_map; // gives error: ‘std::pair<_T1, _T2>::second’ has incomplete type
};

int main() {
  return 1;
}

std::map works std::unordered_map does not work. Any Ideas why this is the case, or what can be done to get it to work with a std::unordered_map?


回答1:


I guess that because std::unordered_map needs to rehash, and therefore copy elements, the types need to be complete, whereas a map, only ever working with pointers to elements, will not exhibit that problem.

The solution here is to have an unordered map to a pointer:

std::unordered_map<uint32_t, std::shared_ptr<Test> >. 



回答2:


Using both map and unordered_map with incomplete types involves undefined-behavior:

In particular, the effects are undefined in the following cases:

[...]

— if an incomplete type (3.9) is used as a template argument when instantiating a template component, unless specifically allowed for that component.



来源:https://stackoverflow.com/questions/8452566/why-cant-i-replace-stdmap-with-stdunordered-map

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!