如果反射性地为真,那么C ++中std :: map中的compare函数如何工作?

时间:2014-07-11 02:03:38

标签: c++ stl stdmap

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

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 here的cplusplus文档页面上,它说出来并引用

  

地图对象的比较对象在构造时设置。其类型(成员key_compare)是地图模板的第三个模板参数。默认情况下,这是一个较小的对象,它返回与运算符“&lt;”相同的。

     

此对象确定容器中元素的顺序:它是一个函数指针或一个函数对象,它接受两个与元素键相同类型的参数,如果第一个参数被认为是在第二个是它定义的严格弱序,否则就是假。

     

如果key_comp以反射方式返回false,则认为两个键是等效的(即,无论键作为参数传递的顺序如何)。

但这并没有说明它是反射性true的情况。谁能告诉我它的行为会是什么呢?或者我应该只通过迭代整个地图来进行间隔比较吗?

3 个答案:

答案 0 :(得分:9)

  1. std::map中使用的比较器必须提供strict weak ordering个对象。
  2. 你的比较器没有。
  3. 因此,您的std::map实例将产生未定义的行为。
  4. 注意:让比较器提供总排序通常会更容易。

    此外,让我们描述严格的弱排序需要什么。在这里,我将摘录 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)
    

答案 1 :(得分:4)

为什么不将它用作比较器?

return minwidth < (y - x);

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

答案 2 :(得分:1)

实际上,如果你用这种方式重写比较器,它应该可以工作:

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>,因此您可以检查插入是否成功。