std :: set :: insert:使用用户定义的类重复

时间:2015-10-21 19:10:58

标签: c++ insert set duplicates

我正在使用C ++ set容器来删除重复项,但是我遇到了用户定义类的问题。我将比较运算符定义如下,效果很好:

bool operator < (const TLineSegment& other) const
{
    int cx1 = (int)((x1 + x2) / 2.0);
    int cy1 = (int)((y1 + y2) / 2.0);
    int cx2 = (int)((other.x1 + other.x2) / 2.0);
    int cy2 = (int)((other.y1 + other.y2) / 2.0);

    if (cx1 == cx2)
        return (cy1 < cy2);
    else
        return (cx1 < cx2);
}

但是,下面的代码通过添加更多条件(在一定范围内没有重复)包含很少的重复项。我发现它在大多数情况下都有效,但它有时不起作用,真的很奇怪。我发现的一个案例是两个TLineSegments是相同的(但不是同一个实例),并且它们都插入了。

bool operator < (const TLineSegment& other) const
{
    const int epi = 5;
    int cx1 = (int)((x1 + x2) / 2.0);
    int cy1 = (int)((y1 + y2) / 2.0);
    int cx2 = (int)((other.x1 + other.x2) / 2.0);
    int cy2 = (int)((other.y1 + other.y2) / 2.0);

    if (abs(cx1 - cx2) < epi) {
        if (abs(cy1 - cy2) < epi) {
            return false;
        }
        else {
            return (cy1 < cy2);
        }
    }
    else {
        return (cx1 < cx2);
    }

1 个答案:

答案 0 :(得分:0)

我们将线段(-n,0):(n,0)与线段(-x,-y):(x,y)进行比较。因此(cx1,cy1)(cx2,cy2)都是(0,0)。对于operator<的两种实现,结果在任一方向上都是false,这意味着两个线段是等效的。也就是说,以(0,0)为中心的任何线段都等同于其他所有这样的线段?!

这显然是不正确的。

最简单的方法是利用定义operator<的{​​{3}}并执行以下操作:

std::tuple<int, int, int, int> tied() const {
    // can be just auto in C++14. typically I'd say use std::tie()
    // but we're dealing with ints right?
    return std::make_tuple(x1, y1, x2, y2);
}

bool operator < (const TLineSegment& other) const
{
    return tied() < other.tied();
}