Я пытаюсь использовать 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) является дорогостоящей по сложности.
Может у кого-нибудь есть идея?
Вам нужно реализовать строгий слабый порядок <
для вашего класса. Самый простой способ — использовать лексикографический порядок, предоставленный 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);
}
// ...
};
@OP: std::set
это уникальный, заказанный контейнер. Это требует либо operator<
или компаратор, переданный явно, который реализует строгий слабый порядок.
если ты не хочу навести порядок на ваших элементах, не использовать заказанный контейнер. Ты можешь использовать std::unordered_set
если вы просто хотите обнаружить уникальность без наложения заказа.
Вы должны объявить оператора<, Вы можете сделать это так
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;
}
Это произвольно, но это не имеет значения. Пока оператор< дает последовательный заказ, вы будете в порядке.
Вы иметь предоставить оператор сравнения, потому что 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;
}
Вам необходимо предоставить компаратор. Вы не хотите реализовывать 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);