Boost.Intrusive and unordered_map

2019-03-18 18:58发布

I am looking to use an intrusive unordered_map. For some reason there is only an unordered_set in the library. There is also an intrusive hashtable but I'm not sure it has the same functunality, also it doesn't have the same interface.
Am I wrong and I missed the unordered_map link?
If I am not is there a tutorial that will help me implement one?

2条回答
贼婆χ
2楼-- · 2019-03-18 19:23

It's an interesting question. Boost.Intrusive doesn't seem to provide any map interface, ordered or unordered. It has a lot of implementation types that will work fine as maps both ordered (red-black trees, AVL trees, splay trees) and unordered (hashtables). But no maps and I couldn't tell you why.

You have two choices as I see it:

  1. Just use hashtable: the unordered containers are implemented as hashtables (and the only reason they aren't called hash_map is to avoid name collisions with pre-existing libraries using that name already). That will work if you want to get your work done.
  2. If you really want to implement your own, you want to take a look at the interface description for Boost.Intrusive's unordered_set. I have not looked at the implementation but it is almost certainly a wrapper around one or more of the tree types. std::set and std::map are both typically implemented as wrappers around a red-black tree (in all standard library implementations I've looked at: GCC's, MSVC's, and Apache's stdcxx). Also take at how libstdc++ wraps their tree implementation in <map> and in <set>. It's a lot of boilerplate, much of it tedious but both types defer almost all the work to the tree. Something analogous is almost certainly happening with Boost.Intrusive's unordered_set. You will need to look at the differences between the map and set interfaces, and use that as the basis for modifying unordered_set into unordered_map.

I've done the latter. It's a bit on the tedious side, and I highly highly recommend writing unit tests for it (or stealing the ones that come with libstdc++ or Boost.Intrusive). But it's doable. I also highly recommend reading the requirements documents for sets and maps, either at SGI (set, map) or for libstdc++

Update: I realized why they aren't doing maps: the intrusive containers require that you embed the node information for the data structure in the value type you are storing in it. For maps you would have to do this for both the values and the keys. It's not that this isn't possible, but the standard implementation for a map uses the same internal type as the sets do. But those internal types only have one value_type variable: to store keys and values they copy the key and the value into that variable and store that in the nodes. To do that with an intrusive type (i.e. without copying) you'd have to modify that implementation type to be incompatible with sets: it has to store references to the keys and values separately. So to do it you also have to modify the implementation you use (probably hashtable). Again not impossible, but the library designers are likely trying to avoid serious code duplication so in the absence of simple way to implement this they have most likely decided to leave maps out.

Does that make sense?

查看更多
倾城 Initia
3楼-- · 2019-03-18 19:42

It's been a long time since this question has been asked, but I think people coming here should be interested on how to use an unordered_set as a map. The solution is to use advanced insertions methods: one just has to store a key and its value in the same value_type, and insert it using insert_check and insert_commit.

查看更多
登录 后发表回答