Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ std::set equality

I try to use a std::set in order to have unique elements in my container.

Since I have 3D objects :

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

Those objects are equal when (A.x==B.x && A.y==B.y && A.z==B.z).
In std::set implementation a element A==B if (!(A < B) && !(B>A)).
It's impossible for my comparison... I have tried to overload == operator.
I chose set container for comparing values when I call insert(a). I was doing something like that with std::vector v and his iterator:

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

With

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.
Can someone have an idea ?

like image 505
user1788477 Avatar asked Oct 31 '12 13:10

user1788477


2 Answers

You need to implement a strict weak ordering < 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);
    }

    // ...
};
like image 110
Kerrek SB Avatar answered Sep 29 '22 14:09

Kerrek SB


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

If you don't want to impose an ordering on your elements, don't use an ordered container. You can use std::unordered_set if you just want to detect uniqueness without imposing an ordering.

like image 26
Useless Avatar answered Sep 29 '22 13:09

Useless