std::list Строгий слабый порядок

У меня много проблем с использованием функции std::list::sort, она работает большую часть времени, но время от времени выдает утверждение "недопустимый оператор<". Рассматривая эту проблему, я понял, что это потому, что моя функция сортировки не следует строгому слабому упорядочению, однако, когда я смотрю на свой код, я не понимаю, почему он не следует строгому слабому упорядочению, поскольку кажется правильным, что я пропускаю Вот?

Целью этой функции является сортировка списка элементов в строку формулы на основе системы Hill, т.е. Первый углерод, второй водород, все остальные по алфавиту. FormulaStruct просто представляет отдельный элемент и количество в полной формуле.

struct FormulaStruct
{
    FormulaStruct(const std::string & strSymbol, int nNum, bool bHasCarbon)
        :
            m_strSymbol(strSymbol),
            m_nNum(nNum), m_bHasCarbon(bHasCarbon)
    {
    }

    bool operator < (const FormulaStruct & rhs)
    {
        //If the symbols are equal
        if(m_strSymbol == rhs.m_strSymbol)
            return true;

        if(m_bHasCarbon)
        {       
            if(m_strSymbol == "C")
                return true;        
            else        
            if(rhs.m_strSymbol == "H")
                return false;           
        }

        return m_strSymbol < rhs.m_strSymbol;
    }

    bool operator == (const FormulaStruct & rhs)
    {
        return m_strSymbol == rhs.m_strSymbol;
    }

    std::string m_strSymbol;
    int         m_nNum;
    bool        m_bHasCarbon;
};

list<FormulaStruct> FormulaList; //A list of FormulaStructs, assumed to be filled
FormulaList.sort();

РЕДАКТИРОВАТЬ bHasCarbon - это условие, когда в формуле присутствует углерод, поскольку система Хилла требует, чтобы, если в формуле присутствовал углерод, водород был следующим, в противном случае все в алфавитном порядке, включая водород, это продиктовано в другом разделе моего кода.

2 ответа

Решение

Другие ответы уже адресованы m_strSymbol == rhs.m_strSymbol вопрос.

Но, исходя из вашего описания (сначала "C", затем "H", все остальное в порядке), кажется, что вы могли бы захотеть, если у вас есть C++11:

return std::tie(m_strSymbol != "C", m_strSymbol != "H", m_strSymbol)
    < std::tie(rhs.m_strSymbol != "C", rhs.m_strSymbol != "H", rhs.m_strSymbol);

Это простой способ написать StrictWeakOrderings (украдено отсюда)

Или, если у вас нет C++11 (или Boost pre-C++11), вы можете сделать что-то вроде этого:

// order of checks here is important, in case both are "C"
if(rhs.m_strSymbol == "C")
    return false;
if(m_strSymbol == "C")
    return true;
// neither symbol is "C"
if(rhs.m_strSymbol == "H")
    return false;
if(m_strSymbol == "H")
    return true;
// neither symbol is "C" or "H"
return m_strSymbol < rhs.m_strSymbol;

Я почти уверен, что сделал это правильно, но, как указано в статье, опубликованной выше, выполнение этого вручную подвержено ошибкам, и, вероятно, его следует избегать... кроме того, это может быть дополнительно оптимизировано, чтобы уменьшить количество сравнений строк, на риск введения ошибок и запутывания кода.

Но неясно, что означает m_bHasCarbon и какой эффект он должен иметь, так что я не уверен, нужно ли вам это или нет.

//If the symbols are equal
if(m_strSymbol == rhs.m_strSymbol)
        return true;

Это означает, что это верно для обоих a<b а также b<a если символы равны

Возможно, вам следует return false, поскольку a==b и поэтому !a<b, в этом случае.

Также ваш второй набор сравнений сбивает с толку.. что m_bHasCarbon,

Другие вопросы по тегам