8

同様の問題がこのリンクで回答されていることは知っていますが、この C++ std::set コンパレーターを修正する のに役立ちますが、残念ながらまったく同じ問題に直面しており、その背後にある理由を理解できないため、解決するための助けが必要です。

私は VS2010 を使用しており、リリース バイナリは問題なく正常に動作していますが、デバッグ バイナリは次のように報告します。

ここに画像の説明を入力

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

struct PathComp {
    bool operator() (const wchar_t* path1, const wchar_t* path2) const
    {
        int c = wcscmp(path1, path2);
        if (c < 0 || c > 0) {
            return true;
        }
        return false;
    }
};

私のセットは次のように宣言されています:

set<wchar_t*,PathComp> pathSet;

デバッグ バイナリがこのアサーションで失敗する理由を教えてください。セットに格納されているワイド文字列を比較するために wcscmp() 関数を使用しているためですか?

前もって感謝します!!!

4

3 に答える 3

18

std::setoperator<またはのように動作する有効な演算子が必要ですstd::less

std::set コードは、あなたの operator< が無効であることを検出し、あなたの助けとして、あなたが示したアサートをトリガーしました。

そして確かに:あなたのコンパレータはのようでoperator!=はなく、のように見えますoperator<

operator<が従うべき規則の 1 つは、a<bとのb<a両方が true であってはならないということです。あなたの実装では、そうです。

コードを次のように修正します。

bool operator() (const wchar_t* path1, const wchar_t* path2) const
{  
  int c = wcscmp(path1, path2);
  return (c < 0);
}

そしてあなたは大丈夫なはずです。

于 2011-05-04T16:25:48.727 に答える
9

問題は、コンパレーターが厳密な弱い順序付けを誘発しないことです。異なるすべてのパスではなく、「少ない」パスに対してのみ true を返す必要があります。次のように変更します。

struct PathComp {
    bool operator() (const wchar_t* path1, const wchar_t* path2) const
    {
        int c = wcscmp(path1, path2);
        if (c < 0) {  // <- this is different
            return true;
        }
        return false;
    }
};

または、 onlyc > 0を使用しても機能しますが、セットの順序が逆になります。

アルゴリズムが機能するには、小さいものと大きいものの違いを知る必要があります。等しくないだけでは十分な情報が得られません。より小さい/より大きい情報がなければ、セットはおそらく順序を維持できませんが、それがセットのすべてです。

于 2011-05-04T16:25:37.823 に答える
1

After spending some more time on it we finally decided to take another approach which worked for me.

So we converted wchar_t* to string using this method:

// Converts LPWSTR to string
bool convertLPWSTRToString(string& str, const LPWSTR wStr)
{
    bool b = false;
    char* p = 0;
    int bSize;    
    // get the required buffer size in bytes
    bSize = WideCharToMultiByte(CP_UTF8,
        0,
        wStr,-1,
        0,0,
        NULL,NULL);     
    if (bSize > 0) {
        p = new char[bSize];
        int rc = WideCharToMultiByte(CP_UTF8,
            0,
            wStr,-1,
            p,bSize,
            NULL,NULL);
        if (rc != 0) {
            p[bSize-1] = '\0';
            str = p;
            b = true;
        }
    }
    delete [] p;
    return b;
}

And then stored that string in the in the set, by doing this I didn't had to worry about comparing the elements getting stored to make sure that all entries are unique.

// set that will hold unique path
set<string> strSet;

So all I had to do was this:

string str;
convertLPWSTRToString(str, FileName);
// store path in the set
strSet.insert(str);

Though I still don't know what was causing "Debug Assertion Failed" issue when I was using a set comparator (PathComp) for set<wchar_t*,PathComp> pathSet;

于 2011-05-04T10:04:34.240 に答える