C ++ std :: set equality

I am trying to use std::set to have unique elements in my container.

Since I have 3D objects:

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

These objects are equal at (Ax==Bx && Ay==By && Az==Bz) .
The std :: set element implements A==B if (!(A < B) && !(B>A)) .
This is not possible for my comparison ... I tried to overload the == operator.
I chose a container to compare values ​​when calling insert(a) . I did something similar with std::vector v and its iterator:

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

FROM

 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; } 

Checking it for each object (10000-100000) is expensive in complexity.
Maybe someone has an idea?

+6
source share
5 answers

You need to implement a strict weak order < for your class. The easiest way is to use the lexicographic ordering provided by 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
source

@OP: std::set is a unique, ordered container. This requires either operator< , or the comparator is passed explicitly, which implements a strict weak order.

If you do not want to place an order on your items, do not use an ordered container. You can use std::unordered_set if you just want to define uniqueness without imposing order.

+4
source

You need to provide a comparison operator because std::set needs it to implement it.

A simple smaller statement would look like this:

 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
source

You must declare the operator <. You can do it like this:

 bool operator<(const Object3D& a, const Object3D& b) { if (ax < bx) return true; if (bx < ax) return false; if (ay < by) return true; if (by < ay) return false; if (az < bz) return true; if (bz < az) return false; return false; } 

This is arbitrary, but it does not really matter. As long as the <operator gives a sequential order, everything will be all right.

+1
source

You need to provide a comparator. You do not want to implement operator< , and I agree with this solution. You should not provide meaningless functions for your class to satisfy the limitations of any container. Fortunately, you do not need operator< . But you need a function with behavior similar to operator< . This does not mean that one object is considered smaller than another. It just needs to ensure a strictly weak order. You can give him any name you want. For instance:

 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(); } 

Then you provide this function to your set constructor:

 typedef bool(*compT)(const Object3D&, const Object3D&); std::set<Object3D,compT> objects(Compare_by_x_then_y_then_z); 
+1
source

All Articles