6

可以在创建和初始化 std::map 后更改它的比较方法吗?或者也许只有在它被创建之后?

我想以某种方式更改包含无法更改定义的映射的类的行为。我想通过传递另一张地图来改变它的比较行为。

4

4 回答 4

4

也许有可能,这是未经测试的:

  1. 定义你自己的自定义比较器,它内部有一个指向比较函数真正实现的指针
  2. 将 this 的实例传递给地图的构造函数(您也必须使用此比较器键入地图。)
  3. 稍后设置真正的实现(在使用地图之前),如果你设置它之后,你不知道对内部的影响......

已经测试过,可以做到以上几点,但是如果树中有项目,更改比较功能可能是灾难性的......

无论如何-这听起来太可疑了....

于 2012-12-18T14:42:58.130 回答
2

不,那是不可能的。比较器是地图类型的一部分。这个问题与询问您是否可以更改int存储浮点数没有什么不同。

更重要的是,比较器提供的排序是映射内部结构的一个组成部分。如果您要更改排序,则数据结构将不再处于一致状态。唯一可行的选择是根据新顺序从旧地图的元素重建新地图,但这已经是可能的:

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

或者,您可以制作第二个类型的地图std::map<std::reference_wrapper<T const>, std::reference_wrapper<V>, Comp2>并使用对原始地图的引用填充它,但根据Comp2. 在这种情况下,您有责任保持两个地图同步。像 Boost.Multiindex 这样的高级容器可以安全地为您执行此操作。

于 2012-12-18T15:00:29.033 回答
1

这不可能。但是您可以创建一个新映射,使用替代比较条件和两个迭代器构造函数来使用第一个中的元素实例化映射。

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());
于 2012-12-18T14:43:51.847 回答
1

不,这是不可能的,因为它是通过模板参数编译到地图中的。

请参阅:http ://www.cplusplus.com/reference/map/map/ 比较是您正在寻找的。

你想做什么?

由于您将类作为 Key 使用,因此您可以实现 < 运算符或 compare 函数来对上下文做出反应。由于您可以将完全构造的对象作为比较函数传递给构造函数,因此应该可以传递所有内容以实现依赖于上下文的同情。问题是,你为什么要这样做?

在运行时更改 std::map 的比较是一个坏主意,因为它会导致未定义的行为。仅仅基于 std::map 的内容是“排序的”(可能是 RB-tree)这一事实。如果你改变排序函数,你会突然改变逻辑顺序;但地图不会神奇地重新排序。下一次调用 insert 或 find 可能不会达到您的预期。

于 2012-12-18T14:51:54.973 回答