8

我尝试使用 astd::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))
我的比较是不可能的......我试图重载==运算符。
我在调用时选择了 set container 来比较值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)检查它的复杂性很高。
有人可以有一个想法吗?

4

5 回答 5

7

您需要<为您的班级实施严格的弱排序。最简单的方法是使用提供的字典顺序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);
    }

    // ...
};
于 2012-10-31T13:16:02.603 回答
5

@OP:std::set是一个独特的有序容器。它需要operator<显式传递一个或一个比较器,这实现了严格的弱排序。

如果您不想对元素强加排序,请不要使用有序容器。std::unordered_set如果您只想检测唯一性而不强加排序,则可以使用。

于 2012-10-31T13:22:29.070 回答
2

您需要提供一个比较器。你不想实施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);
于 2012-10-31T13:35:26.873 回答
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;
}
于 2012-10-31T13:09:32.527 回答
1

您必须声明运算符<。你可以这样做

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

这是任意的,但这并不重要。只要 operator< 给出一致的顺序,你就可以了。

于 2012-10-31T13:12:07.437 回答