djWann
djWann

Reputation: 2127

std::map change key_comp after initialization

It is possible to change the comparison method of a std::map after it has been created and initialized? Or maybe only after it has been created??

I want to alter somehow the behavior of a class that contains a map that I cannot change the definition. I want to change it's comparison behavior maybe by passing another map.

Upvotes: 6

Views: 4068

Answers (4)

juanchopanza
juanchopanza

Reputation: 227608

It is not possible. But you can create a new map, with the alternative comparison criteria, and the two iterator constructor to instantiate the map using the elements from the first one.

bool  C1(const K&, const K&);
bool  C2(const K&, const K&);

std::map<K, V, C1> orig;
....
std::map<K, V, C2> alternative(orig.begin(), orig.end());

Upvotes: 1

Kerrek SB
Kerrek SB

Reputation: 477620

No, that is not possible. The comparator is part of the type of the map. The question is no different from asking whether you can change an int to store floating point numbers.

More importantly, the ordering provided by the comparator is an integral part of the internal structure of the map. If you were to change the ordering, the data structure would no longer be in a consistent state. The only feasible option is to rebuild a new map from the old map's elements with respect to the new order, but that's already possible:

std::map<T, V, Comp1> m1 = /* ... */;
std::map<T, V, Comp2> m2(m1.begin(), m1.end());

Alternatively, you can make a second map of type std::map<std::reference_wrapper<T const>, std::reference_wrapper<V>, Comp2> and populate it with references to the original map, but ordered according to Comp2. In that case it is your own responsibility to maintain the two maps in sync. An advanced container like Boost.Multiindex can do this for you in a safe fashion.

Upvotes: 3

Nim
Nim

Reputation: 33655

Maybe it is possible, this is untested:

  1. Define your own custom comparator, which internally has a pointer to the real implementation of the comparison function
  2. Pass an instance of this to the constructor of the map (you have to type the map using this comparator too.)
  3. Set the real implementation later (before using the map), if you set it after, you don't know the impact on the internals...

Have tested, and it is possible to do the above, however changing the comparison function if there are items in the tree can be disastrous...

Anyway - it all sounds too fishy....

Upvotes: 4

rioki
rioki

Reputation: 6128

No it is not possible, since it is compiled into the map via a template argument.

See: http://www.cplusplus.com/reference/map/map/ Compare is what you are looking for.

What are you trying to do?

Since you have the class in the hand you are using as Key, you could implement either the < operator or the compare function to react to context. Since you can pass a fully constructed object to the constructor as comparison function it should be possible to pass everything along to implement a context dependent compassion. The question is, why would you want to?

It is a bad idea to change the comparison of std::map while it runs, because it will result in undefined behavior. Simply based on the fact that the contents of std::map is "sorted" (probably a RB-tree). If you change the ordering function you will suddenly change logical order; but the map will not magically reorder itself. The next call to insert or find will probably not do what you expect.

Upvotes: 1

Related Questions