Получение "Ошибка отладки!" для набора компаратора - PullRequest
7 голосов
/ 28 апреля 2011

Я знаю, что на подобную проблему был дан ответ по этой ссылке Помогите мне исправить это C ++ std :: set compara * но, к сожалению, я сталкиваюсь с точно такой же проблемой, и я не могу понять причину ее возникновения, поэтому мне нужна помощь для ее решения.

Я использую VS2010, и мой двоичный файл релиза работает нормально без каких-либо проблем, но отчеты об отладочных двоичных файлах:

enter image description here

Мой компаратор выглядит так:

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 () для сравнения строки широких символов, хранящейся в моем наборе?

Заранее спасибо !!!

Ответы [ 3 ]

15 голосов
/ 04 мая 2011

std::set требует действительного компаратора, который ведет себя как operator< или std::less.

Код std :: set обнаружил, что ваш оператор <недопустим, и в качестве справки вы вызвалиутверждаю, что вы показали. </p>

И действительно: ваш компаратор выглядит как operator!=, а не operator<

Одно из правил, которым должен следовать operator<, заключается в том, что a<bи b<a не может быть и правдой.В вашей реализации это так.

Исправьте ваш код следующим образом:

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

и все будет в порядке.

9 голосов
/ 04 мая 2011

Проблема в том, что ваш компаратор не вызывает строго-слабый порядок.Он должен действительно возвращать 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;
    }
};

В качестве альтернативы, использование только c > 0 также будет работать - но набор будет иметь обратный порядок.

Алгоритм должен знать разницу между меньшим и большимработать, просто неравный не дает достаточно информации.Без информации «меньше / больше» набор не может поддерживать порядок, но именно в этом и состоит набор.

1 голос
/ 04 мая 2011

Потратив немного больше времени на это, мы наконец решили использовать другой подход, который работал для меня.

Итак, мы преобразовали wchar_t * в строку, используя этот метод:

// 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;
}

И затем сохранил эту строку в наборе, делая это, мне не пришлось беспокоиться о сравнении сохраняемых элементов, чтобы убедиться, что все записи уникальны.

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

Итак, все, что мне нужно было сделать, это:

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

Хотя я до сих пор не знаю, что вызывало проблему «Ошибка отладки» при использовании a set comparator (PathComp) for set<wchar_t*,PathComp> pathSet;

...