“无效的比较器”:重载“ <”运算符时出错

Roh*_*tra 5 c++ sorting operator-overloading

我有一堂课需要排序。使用此类的向量,排序时出现错误“无效比较器”。

我在课堂上超载了“ <”运算符,并遵循严格的弱排序

如本帖所述

sort需要严格的弱排序。你comparator不是一个。除其他外,对于严格的弱排序,comp(x, x)必须为

这是我的代码:

bool outlierScore::operator<(const outlierScore& other) {
    if (score < other.score)
        return score < other.score;
    else if (coreDistance < other.coreDistance)
        return coreDistance < other.coreDistance;
    else if (id < other.id)
        return id < other.id;
    else
        return false;
}
Run Code Online (Sandbox Code Playgroud)

这是重载的运算符函数,它的作用实际上是尝试按离群值按升序排序,其中核心距离用于打破离群值关系,而id用于打破核心距离关系。

Stack Trace显示了此阶段出现的错误。

template <class _Pr, class _Ty1, class _Ty2>
constexpr bool _Debug_lt_pred(_Pr&& _Pred, _Ty1&& _Left, _Ty2&& _Right) _NOEXCEPT_COND(
    noexcept(_Pred(_Left, _Right))
    && noexcept(_Pred(_Right, _Left))) { // test if _Pred(_Left, _Right) and _Pred is strict weak ordering
    const auto _Result = static_cast<bool>(_Pred(_Left, _Right));
    if (_Result) {
        _STL_VERIFY(!_Pred(_Right, _Left), "invalid comparator");
    }

    return _Result;
}
Run Code Online (Sandbox Code Playgroud)

我找不到问题。任何帮助都会很棒。

最小的可重复的例子

class outlierScore
{
private:
    double coreDistance;
public:
    double score;
    int id;
}
vector <vector<double>> x = {
                {0,0.889528896739179,0.536626916823739},
                {1,1.30766765703343,0.684794721931497},
                {2,0.936505261432846,0.559870334496815}
            };
vector<outlierScore> test;
test.push_back(outlierScore(x[0][2], x[0][1], x[0][0]));
test.push_back(outlierScore(x[1][2], x[1][1], x[1][0]));
test.push_back(outlierScore(x[2][2], x[2][1], x[2][0]));
Run Code Online (Sandbox Code Playgroud)

包含outlierScore对象,看起来像 {id, coreDistance, score}

出现错误的地方: sort(test.begin(), test.end());

DAl*_*Ale 10

您的实现不正确。

bool outlierScore::operator<(const outlierScore& other) const {
    return (score < other.score) ||
           (score == other.score && coreDistance < other.coreDistance) ||
           (score == other.score && coreDistance == other.coreDistance && id < other.id);
}
Run Code Online (Sandbox Code Playgroud)

要么

bool outlierScore::operator<(const outlierScore& other) const {
    return std::tie(score, coreDistance, id) < std::tie(other.score, other.coreDistance, other.id);
}
Run Code Online (Sandbox Code Playgroud)

  • 我可以在第一个示例中建议一些括号吗?对于人类,不是编译器! (3认同)
  • @BoBTFish:我也不能;-)。对我而言,获得的顺序几乎是(i)学习键入,(ii)学习使用调试器,(iii)学习优先级表,(iv)学习语法。我强烈反对在我的商店中放入多余的括号。它们有时是有害的:例如,奖金=薪水*(9/10)。 (3认同)
  • @Bathsheba我不能完全拒绝在评论中进行有争议的辩论的诱惑:p也许作为一位经验丰富的C ++专家,您会发现遵循优先级规则很容易,因此会发现多余的parens噪音,甚至导致您浪费脑力。寻找他们如何改变逻辑。但是,也许对于不那么熟悉规则的人(因为我怀疑这个答案是相对的初学者),请家长帮忙? (2认同)
  • @Bathsheba我和你在一起。对我来说,就像写`(a * b)+ c`而不是`a * b + c`一样。话虽如此,我们不是一个孤独的程序员,即使大多数人对我们的可读性不高,他们也必须遵循大多数人认为更易懂的东西。 (2认同)

Mic*_*ler 10

除了方法不是之外const,此运算符不满足严格的弱排序。

bool outlierScore::operator<(const outlierScore& other) {
    if (score < other.score)
        return score < other.score;
    else if (coreDistance < other.coreDistance)
        return coreDistance < other.coreDistance;
    else if (id < other.id)
        return id < other.id;
    else
        return false;
}
Run Code Online (Sandbox Code Playgroud)

例如,如果所有字段都是整数。

a.score = 0 ; a.coreDistance = 1
b.score = 1 ; b.coreDistance = 0
Run Code Online (Sandbox Code Playgroud)

对于这些值,以下应该为false,但返回true:

a < b && b < a
Run Code Online (Sandbox Code Playgroud)

您还应该检查是否相等:

bool outlierScore::operator<(const outlierScore& other) {
    if (score != other.score)
        return score < other.score;
    else if (coreDistance != other.coreDistance)
        return coreDistance < other.coreDistance;
    else 
        return id < other.id;
}
Run Code Online (Sandbox Code Playgroud)