c ++ std :: установить равенство

Я пытаюсь использовать std::set чтобы иметь уникальные элементы в моем контейнере.

Так как у меня есть 3D-объекты:

Class Object3D{
private:
float x;
float y;
float z;
}

Эти объекты равны, когда (A.x==B.x && A.y==B.y && A.z==B.z),
В реализации std :: set элемент A==B if (!(A < B) && !(B>A)),
Это невозможно для моего сравнения … Я попытался перегрузить == оператор.
Я выбрал набор контейнеров для сравнения значений при вызове insert(a),
Я делал что-то подобное с std::vector v и его итератор:

if(!(A).inVector()){
v.push_back(A);
}

С

bool inVector(){
for(itr = v.begin();itr != v.end();itr++){
if(this->x==(*itr)->x && this->y==(*itr)->y && this->z==(*itr)->z){
return true;
}
}
return false;
}

Проверка его для каждого объекта (10000-100000) является дорогостоящей по сложности.
Может у кого-нибудь есть идея?

6

Решение

Вам нужно реализовать строгий слабый порядок < для вашего класса. Самый простой способ — использовать лексикографический порядок, предоставленный tuple:

#include <tuple>

class Object3D
{
public:
bool operator<(Object3D const & rhs) const
{
return std::tie(x, y, z) < std::tie(rhs.x, rhs.y, rhs.z);
}

// ...
};
7

Другие решения

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

если ты не хочу навести порядок на ваших элементах, не использовать заказанный контейнер. Ты можешь использовать std::unordered_set если вы просто хотите обнаружить уникальность без наложения заказа.

4

Вы должны объявить оператора<, Вы можете сделать это так

bool operator<(const Object3D& a, const Object3D& b)
{
if (a.x < b.x) return true;
if (b.x < a.x) return false;
if (a.y < b.y) return true;
if (b.y < a.y) return false;
if (a.z < b.z) return true;
if (b.z < a.z) return false;
return false;
}

Это произвольно, но это не имеет значения. Пока оператор< дает последовательный заказ, вы будете в порядке.

1

Вы иметь предоставить оператор сравнения, потому что std::set нужно для его реализации.

Простой оператор меньше чем будет выглядеть так:

bool Object3D::operator<(const Object3D& other) const {
if(x != other.x) return x < other.x;
if(y != other.y) return y < other.y;
return z < other.z;
}
1

Вам необходимо предоставить компаратор. Вы не хотите реализовывать operator<и я согласен с этим решением. Вы не должны предоставлять бессмысленные функции для вашего класса только для того, чтобы удовлетворить ограничения некоторого контейнера. К счастью, вам не нужно operator<, Но вам нужна функция, поведение которой похоже на operator<, Это не должно имею в виду что один объект считается меньше, чем другой. Нужно просто обеспечить строго-слабый порядок. Вы можете дать ему любое имя. Например:

bool Compare_by_x_then_y_then_z(const Object3D& lhs, const Object3D& rhs)
{
if (lhs.getX() != rhs.getX()) return lhs.getX() < rhs.getX();
if (lhs.getY() != rhs.getY()) return lhs.getY() < rhs.getY();
return lhs.getZ() < rhs.getZ();
}

Затем вы предоставляете эту функцию конструктору вашего набора:

typedef bool(*compT)(const Object3D&, const Object3D&);
std::set<Object3D,compT> objects(Compare_by_x_then_y_then_z);
1
По вопросам рекламы [email protected]