insert into std::set
Как заполнить 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 (комменты)
Ответы (2 шт):
Если у 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 может посчитать различающиеся пары одинаковыми, и отказаться вставлять одну если внутри уже есть другая. Что вы и видели с вашим кодом порядка.
Я предложил бы оптимизированный вариант первого ответа. В плане эффективности битовая операция, особенно с одним битом, куда быстрей чем несколько сравнений:
bool operator <(const para& r) const {
return (flag ^ r.flag) ? r.flag : x < r.x;
}