c++中std::map中的compare函数如果自反为真,该如何工作?

How does the compare function in std::map in C++ work if it is reflexively true?

本文关键字:何工作 工作 中的 map std compare 函数 c++ 如果      更新时间:2023-10-16

我有一个地图在我的项目。每次插入新元素时,我都希望确保所插入的新元素的键至少与映射中的其他元素有最小的距离。为此,我编写了一个自定义比较类,如下所示:

class PulseCompare
{
public:
    PulseCompare(int minwidth_):minwidth(minwidth_){};
    bool operator()(const int x, const int y) const {
        if(abs(x-y)>minwidth) return false;
        else return true;
    }
private:
    int minwidth;
};

并创建如下的映射:

std::map<int,float,PulseCompare> pulsemap(PulseCompare(256));

在我插入一个元素之前,我使用map.find方法,像这样:

if ( pulsemap.find(1600) == pulsemap.end() ) {
  // not found so I can insert
} else {
  // found
}

但问题是,当map试图使用上述比较函数通过交换xy的值进行反射性比较时,它将得到两个情况下的true,而<>等正常比较操作符通常不会出现这种情况

std::map::key_comp的cplusplus文档页面上,这里说,我引用

map对象的比较对象在构造时设置。它的类型(成员key_compare)是映射模板的第三个模板形参。默认情况下,这是一个less对象,返回与操作符"<"相同的结果。

该对象决定容器中元素的顺序:它是一个函数指针或接受与元素键相同类型的两个实参的函数对象,如果按照其定义的严格弱顺序认为第一个实参在第二个实参之前,则返回true,否则返回false。

如果key_comp自反性地返回false(即,无论键作为参数传递的顺序如何),则认为两个键是等价的。

但这并没有说明它是自反性的true的情况。有谁能告诉我它到时候会是什么样子吗?或者我应该只通过遍历整个映射来进行区间比较?

  1. std::map中使用的比较器必须提供对象的严格弱排序。
  2. 您的比较器没有。
  3. 因此,你的std::map实例将产生未定义的行为。

注意:通常让比较器提供总排序更容易。

另外,让我们描述严格弱排序需要什么。这里,我摘自c++ 2011,第25.4节。

  • 你将创建一个函子Compator comp;,我将把comp(lhs, rhs)称为返回布尔值的函数。把它想象成lhs < rhs是有帮助的。
  • 我们将创建一个函数equiv(lhs, rhs)。这被定义为(!comp(lhs, rhs) && !comp(rhs, lhs))。所以,!(lhs < rhs) && !(rhs < lhs) .

我们需要遵守以下规则:

comp(a, b) && comp(b, c) implies comp(a, c)
equiv(a, b) && equiv(b, c) implies equiv(a, c)

为什么不直接使用它作为比较器呢?

return minwidth < (y - x);

下面是一个工作示例:http://coliru.stacked-crooked.com/a/e115d3a2f6714773

实际上,如果您这样重写比较器,它应该可以工作:

bool operator()(const int x, const int y) const {
    if(abs(x-y)<=minwidth) return false;
    else return x < y;
}

你不需要在插入之前使用find,你在做双重工作。只要尝试插入,如果这样的键存在,map将拒绝插入。std::map::insert还返回std::pair<iterator,bool>,因此您可以检查插入是否成功。