【问题标题】:C++: “invalid comparator” assert [duplicate]C ++:“无效的比较器”断言[重复]
【发布时间】:2017-08-30 17:48:46
【问题描述】:

代码如下:

struct Payment
{
    Payment(time_t time, float money) : mTime(time), mMoney(money) {}
    bool operator==(const Payment& p) const // exact comparison
    {
        return mTime == p.mTime && mMoney == p.mMoney;
    }
    time_t  mTime;
    float   mMoney;
};

std::vector<Payment>    payments;

auto sortP = [](const Payment& p1, const Payment& p2) { return p1.mTime < p2.mTime || p1.mMoney <= p2.mMoney; };
std::sort(payments.begin(), payments.end(), sortP);

std::sort(并非总是如此,但有时,当两个元素彼此靠近的mTime 时)在 Visual Studio 2015 中引发无效的比较器断言。代码有什么问题?

【问题讨论】:

  • || p1.mMoney &lt;= p2.mMoney 应该是|| ((p1.mTime == p2.mTime) &amp;&amp; (p1.mMoney &lt; p2.mMoney)) 否则当p1.mTime 大于p2.mTimep1.mMoney 小于p2.Money 时比较会出错。
  • 比较两个浮点数不是一个好主意,浮点数没有精确表示,它们是近似值。您需要比较差异小于某个增量。出于同样的原因,将钱存入浮动资产并不是一个好主意。
  • @VTT:你说得对,这就是解决方案。把它作为一个答案,我会接受的。
  • 一般来说,你不能使用&lt;=来进行严格的弱排序,因为它要求相等的元素为false。
  • @AndersK。在这种情况下,不需要 delta,除非 OP 使用该标准来查找元素。对于实际排序,它可能会使其变慢。

标签: c++ c++11 stl


【解决方案1】:

问题在于sortP 的实现。它不满足严格的弱排序标准。在http://www.sgi.com/tech/stl/StrictWeakOrdering.html阅读详细信息。

我建议进行以下更改:

auto sortP = [](const Payment& p1, const Payment& p2)
{
   // Order by mTime if they are not equal.
   if ( p1.mTime != p2.mTime)
   {
     return p1.mTime < p2.mTime;
   }

   // Otherwise, order by pMoney
   return ( p1.mMoney < p2.mMoney); // Use < not <=
};

您可以使用std::tie 来简化实现。

auto sortP = [](const Payment& p1, const Payment& p2)
{
   return std::tie(p1.mTime, p1.mMoney) < std::tie(p2.mTime, p2.mMoney);
};

【讨论】:

  • 使用std::tie更简单
  • @Slava,当然。感谢您的提示。
【解决方案2】:

|| p1.mMoney &lt;= p2.mMoney 应该是|| ((p1.mTime == p2.mTime) &amp;&amp; (p1.mMoney &lt; p2.mMoney)) 否则当p1.mTime 大于p2.mTimep1.mMoney 小于p2.Money 时比较会出错。确保此类多字段比较器满足严格的弱排序要求的一个好做法是为所有可能的 lt/gt 字段组合编写测试。

【讨论】:

  • 好的做法是使用std::tie
【解决方案3】:

使用c++11,您的比较器 lambda 应该如下所示:

#include <tuple>
...
auto sortP = [](const Payment& p1, const Payment& p2) 
{ 
     return std::tie(p1.mTime, p1.mMoney) < std::tie(p2.mTime, p2.mMoney);
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 2019-03-20
    • 1970-01-01
    • 1970-01-01
    • 2021-01-29
    相关资源
    最近更新 更多