views:

696

answers:

1

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?

Thanks in advance,
Omer.

+4  A: 

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?

quark
So it's not worth the trouble? Because I'm considering time vs. quality here.
the_drow
It's a fair amount of work. The interfaces for the standard containers have a lot of subtleties. I assume the intrusive containers just as much. If time is of the essence go with option 1. If you have time and want to really learn a lot go with option 2.
quark
You said you did it yourself.Do you mind sharing it?
the_drow
Am I missing something obvious? Surely you could store the key in the hook that they you place in the value type, it's just another part of the hook... IMHO the main advantage of the intrusive containers is that they avoid allocation and deallocation for the node, copying the key into the node seems fine... Of course, I *need* a map and it's a pain that they've done all manner of clever kinds of sets and no maps at all!
Len Holgate