insert into std::set<struct>

Рейтинг: 1Ответов: 2Опубликовано: 23.01.2023

Как заполнить std::set элементами стуктуры struct para { bool flag, int x;} ? Причем para(true,100) и para(false,100) считаются разными элементами и должны успешно инсертиться. При вставке срабатывает operator< . видимо для того чтобы вставить элемент куда нужно. Но его использование делается странным.

struct para {
    bool flag;
    int x;
    para(bool i, int x) : flag(i), x(x) {};
    bool operator<(const para& r) const {
        return (r.flag == this->flag || r.x < this->x);                
    }
};
int main()
{
    std::set<para> store1;
    store1.insert(para(false, 10)); //+1 para (нет такой пары в наборе поэтому добавляем её)
    store1.insert(para(true, 10));  //+1 para (нет такой пары в наборе поэтому добавляем её)
    store1.insert(para(true, 11));  //+1 para (нет такой пары в наборе поэтому добавляем её)
    store1.insert(para(true, 10));  //ничего не добавляем в набор (т.к. элемент 
                                    //para(true,10) уже есть в наборе)
}

operator< тут работает не очень очевидно. вопрос как я должен оформить bool operator<(const para& r) const чтобы получить вот такой исход как описан в main (комменты)

Ответы

▲ 3Принят

Если у this и r различаются флаги, упорядочиваем их по флагам. Иначе по значениям x. Порядок получится таким:

  • (false, *) < (true, *)
  • (false, x) < (false, y) если x < y
  • (true, x) < (true, y) если x < y

(false, 1) < (false, 2) < (true, 1) < (true, 2)

Код:

bool operator <(const para& r) const {
    if (!flag && r.flag) {
        return true;
    }
    if (flag && !r.flag) {
        return false;
    }
    return x < r.x;                
}

У это порядка есть важное свойство: если this и r различаются, то или *this < r или r < *this. Если вы нарушаете это правило, set может посчитать различающиеся пары одинаковыми, и отказаться вставлять одну если внутри уже есть другая. Что вы и видели с вашим кодом порядка.

▲ 2

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

bool operator <(const para& r) const {        
    return (flag ^ r.flag) ? r.flag : x < r.x;                
}