8

std::setコンテナに一意の要素を含めるためにa を使用しようとしています。

私は3Dオブジェクトを持っているので:

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

これらのオブジェクトは、 の場合に等しくなり (A.x==B.x && A.y==B.y && A.z==B.z)ます。
std::set 実装では、 element A==B if (!(A < B) && !(B>A)).
私の比較では不可能です...==演算子をオーバーロードしようとしました。
を呼び出すときに値を比較するために set コンテナーを選択しました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

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

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

It is arbitrary, but it doesn't really matter. As long as operator< gives a consistent ordering you'll be OK.

于 2012-10-31T13:12:07.437 に答える