2017-08-30 12 views
1
ここ

はコードです:С++:「無効なコンパレータ」を主張

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年に主張しますコードの何が間違っていますか?
enter image description here

+1

'|| p1.mMoney <= p2.mMoney'は '|| (p1.mTime == p2.mTime)&&(p1.mMoney VTT

+1

2つの浮動小数点数を比較するのは良い考えではありません。浮動小数点数は正確には表現されません。あなたは、その差があるデルタよりも小さいことを比較する必要があります。フロートにお金を入れるのと同じ考え方では良い考えではありません。 –

+0

@VTT:そうです、これが解決策です。それを答えさせて、私は受け入れます。 – deko

答えて

1

|| p1.mMoney <= p2.mMoneyp1.mMoney未満p2.Moneyている間p1.mTimep2.mTimeよりも大きいときにそれ以外の場合は、比較がケースのために間違っているだろう|| ((p1.mTime == p2.mTime) && (p1.mMoney < p2.mMoney))でなければなりません。このようなマルチフィールドコンパレータが厳密な弱い秩序の要件を満たすことを保証するための良い習慣は、フィールドのすべての可能なlt/gtの組み合わせに対するテストを書くことです。以下のようになりますc++11あなたのコンパレータのラムダを使用して

+5

良い例は 'std :: tie'を使うことです – Slava

3

この問題は、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); 
}; 
+3

もちろん、 'std :: tie'を使うのはもっと簡単です。 – Slava

+0

@Slavaです。ヒントをありがとう。 –

1

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