0

カスタム オーダー セットで要素を検索しようとすると問題が発生します。

File: c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree
Line: 1746

Expression: invalid operator<

必要に応じて要素が順序付けられた一連の文字列が必要です。

コンパレータ オブジェクト:

struct OrderComparator {
public:
    static map<string,int> valueOrder;

    bool operator()( const string lhs, const string rhs ) {
        map<string,int>::iterator resultLhs,resultRhs;
        resultLhs = valueOrder.find(lhs);
        resultRhs = valueOrder.find(rhs);
        if (resultLhs == valueOrder.end() || resultRhs == valueOrder.end())
        {
            return false;
        }
        else {
            bool result = resultLhs->second <= resultRhs->second;
            return result;
        }
    }

    static map<string,int> create_map()
    {
        map<string,int> m;
        m["A"] = 1; 
        m["B"] = 2;
        m["C"] = 3;
        m["D"] = 4;
        return m;
    }
};

コンパレータは正常に動作しています。

しかし、セットで検索しようとすると、言及されたエラーが発生します。

typedef set<string, OrderComparator> TREESET_CMP;
...
TREESET_CMP::iterator it = myTree.find(obj); <-fails
...

なぜこれが起こっているのか、それを修正する方法を誰かが教えてくれたらうれしいです.


完全に動作するミニの例:

    #include "stdafx.h"
#include <string>
#include <set>
#include <map>
#include <iterator>
#include <algorithm>
using namespace std;
#include <stdio.h>
#include <tchar.h>

struct OrderComparator {
public:
    static map<string,int> valueOrder;

    bool operator()( const string lhs, const string rhs ) {
        map<string,int>::iterator resultLhs,resultRhs;
        resultLhs = valueOrder.find(lhs);
        resultRhs = valueOrder.find(rhs);
        if (resultLhs == valueOrder.end() || resultRhs == valueOrder.end())
        {
            return false;
        }
        else {
            bool result = resultLhs->second <= resultRhs->second;
            return result;
        }
    }

    static map<string,int> create_map()
    {
        map<string,int> m;
        m["A"] = 1; 
        m["B"] = 2;
        m["C"] = 3;
        m["D"] = 4;
        return m;
    }
};
map<string,int> OrderComparator::valueOrder = OrderComparator::create_map();

typedef set<string, OrderComparator> TREESET_CMP;

int _tmain(int argc, _TCHAR* argv[])
{
    TREESET_CMP myTree;
    myTree.insert("B");
    myTree.insert("C");
    myTree.insert("A");

    TREESET_CMP::const_iterator it = myTree.find("A");
    system("PAUSE");

}
4

3 に答える 3

3

あなたの比較は厳密な弱い順序付けを定義していません

厳密な弱い順序付けには、これらの不変条件が必要です (上記のリンクから引用)

  • 非反射率 f(x, x) は false でなければなりません。
  • 反対称 f(x, y) は !f(y, x) を意味します
  • 推移性 f(x, y) および f(y, z) は、f(x, z) を意味します。
  • 同等性の推移性 同等 性 (上記で定義) は推移的です。x が y と同等であり、y が z と同等である場合、x は z と同等です。(これは、同値が実際に同値関係の数学的定義を満たしていることを意味します。)

あなたのものは、少なくとも非反射性(オブジェクトをそれ自体と比較することは偽である必要があります)と反対称性(xがy未満の場合、yはx未満ではありません)に失敗します

基本的に、セット内の要素が見つからないことを意味する true を返す<=ため、有効な順序付けではありません。x <= x要素を見つけるために、セットはプロパティを持つ要素を探します!cmp(key, element) && !cmp(element, key)が、それは順序付けでは機能しません。

<=に変更するのが最も簡単な修正かもしれませんが<、他にも問題がある可能性があります。

于 2013-03-06T17:52:36.470 に答える
1

コンパレータは次のようになります。

bool operator()( const string &lhs, const string &rhs ) {
    map<string,int>::iterator resultLhs,resultRhs;
    resultLhs = valueOrder.find(lhs);
    resultRhs = valueOrder.find(rhs);
    if (resultLhs == valueOrder.end()) return false;
    if (resultRhs == valueOrder.end()) return true;

    return resultLhs->second < resultRhs->second;
}

2 行を次のように置き換えることができます。

if (resultRhs == valueOrder.end()) return false;
if (resultLhs == valueOrder.end()) return true;

マップに存在しない文字列を並べ替える場合は、その前に並べ替えます。

于 2013-03-06T18:10:00.697 に答える
0

比較方法を宣言しconst、引数に const 参照を使用してみてください。最初の修正は、メソッドの定数バージョンを使用してメソッドを呼び出せるようにすることですOrderComarator。2 番目の修正は、コピーを回避することです。

bool operator()( const string& lhs, const string& rhs ) const {
于 2013-03-06T17:48:24.640 に答える