9

I can't imagine this hasn't been asked, but I'm not having any luck finding it.

Does each element of a multimap contain its value and its key?

That is does the internal structure of a multimap look like more like this:

map<key, vector<value>>

Or more like this:

vector<pair<key, value>>
divibisan
  • 11,659
  • 11
  • 40
  • 58
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288

1 Answers1

11

Each element contains both its key and value.

You can tell because iteration returns a stable non-allocating reference to std::pair<Key const, Value>.

What more, Keys can compare equal but be different. A multimap permits you to store "extra data" in that Key that isn't part of the ordering, and you'll get it back afterwards and it will be associated with that Value.

Implementing a multimap as a std::map<Key, std::vector<Value>> is an option that is sometimes better than using a std::multimap<Key,Value>. Especially with many-values per key, it will be more memory efficient, have better locality, etc. Iterating over it can be trickier if you want to do so uniformly, but if you want to iterate over things clumped by key it is easier.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • 1
    Can you elaborate where it is documented that multimap permits to store "extra data". – Slava Apr 06 '18 at 14:59
  • 2
    @Slava `struct Foo { std::string a; std::string b; bool operator<( Foo const& rhs) const { return a < rhs.a; } };` -- this is a valid `Key` type. It contains both `a` and "extra data" in `b` which is not part of the ordering. If you `insert( { Foo{"hello", "world"}, value );`, the iterator *will* contain a `Foo const` that has `"world"` in the `b`. This isn't all that important for a multimap (why not just put it in the value?), but I've used it for a multiset or set sometimes (however, you can also say "why not just use a map?") – Yakk - Adam Nevraumont Apr 06 '18 at 15:03
  • Yes I understand what that means and it seems reasonable but I cannot find in documentation of multimap such guarantee. For example what prevents it to use copy of existing key instead of supplied one when equivalent one exists for whatever reason. – Slava Apr 06 '18 at 15:06
  • @Slava The general rules of containers? You put X into a container, (a copy of) X is in it. Nothing about map or multimap says "we are permitted to change your X beyond copying it so long as it maintains order". Now, for map, many operations won't actually put X in but will instead modify part of X (m[key]=value for example -- if the key is found, it won't put the key in, it will just modify the value). But those are also specified. However, as far as I know, such APIs are not in multimap, only map. – Yakk - Adam Nevraumont Apr 06 '18 at 15:13
  • Documentation on cppreference says "Multimap is an associative container that contains a sorted list of key-value pairs, while permitting multiple entries with the **same key**." I am not sure general rules of containers can specify what "same key" means. – Slava Apr 06 '18 at 15:17
  • @Slava, extra data is just a property of the key. It comes from the fact that there is no requirement on container's `less` functor to compare all members of the key object. As a result, you can have more data in the key than logical key. I am not sure what is actually confusing, though. – SergeyA Apr 06 '18 at 15:19
  • @Slava cppreference describes things, it doesn't *define* what a multimap is. None of the text on cppreference is normative or defining of what a multimap is, it describes how you use it. If you want to read what a multimap is, read the standard (even draft ones; it is pretty stable). The reading is dense. But the containers are described in a heirarchy of requirements. Associative containers and containers have requirements about what they are independent of the specific container they are. Prose is dense, finding clauses might take hours. – Yakk - Adam Nevraumont Apr 06 '18 at 15:22
  • @Yakk I understand that cppreference is not normative and so that's why I asked do you know what in normatives guarantees such behavior if any. I understand by common sense it should work that way, but it valid to ask if such thing explicitly defined and documented. – Slava Apr 06 '18 at 15:27
  • @SergeyA that 2 equivalent keys could be different objects does not confuse me, just it is not clear that multimap has to keep them as separate objects. – Slava Apr 06 '18 at 15:29
  • 1
    @Slava I am still unclear what do you want from Yakk. What is your real question? Do you think anywhere it requires that container's `less` compare all fields of the key? No. Does it say anywhere that only the fields which are compared by the `less` are guaranteed to be valid in the `key` part of the pair? No. So what is the question than? The fact that multimap has to keep them as two separate objects comes from two facts above. – SergeyA Apr 06 '18 at 15:29
  • @SergeyA I would say question is "is there something in multimap specification that prevents it to keep the same key (or copy of it) for every entry with equal key?" – Slava Apr 06 '18 at 15:32
  • @Slava http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4727.pdf -- look under container and associative container. Table 82 on emplace may help. It places the object in. There are no rules that permit to break what it says it does. So that is the object placed in it. Like I said, it would take hours to construct the prove the statement "container contain the elements you put in them" from standardese, but it is true regardless. If you want a language-lawyer answer, please [Ask a Question] using the button above. This is not the place for a Q&A. – Yakk - Adam Nevraumont Apr 06 '18 at 15:32
  • @Slava, yes, because of what I just said. `equal_range` in multimap returns you iterators to pairs, where pair's `first` is the object key (NOT the comparable part of the key!) – SergeyA Apr 06 '18 at 15:33
  • @Yakk actually normative says "A multimap is an associative container that supports equivalent keys (possibly containing multiple copies of the **same key value**)". I think it means you are wrong there is no such guarantee. – Slava Apr 06 '18 at 15:39
  • @Slava I have already said you should press the [Ask a Question] if you want to discuss this further. Stop posting about it here. (And no, that doesn't mean that) – Yakk - Adam Nevraumont Apr 06 '18 at 15:41
  • Created question here https://stackoverflow.com/questions/49696603/does-stdmultimap-guarantee-actual-value-of-each-key-in-equal-range – Slava Apr 06 '18 at 15:50