4

私は他の人の質問を見たことがありますが、私がここで達成しようとしていることに当てはまるものは見つかりませんでした。

std::sortとaを使用してEntityManagerクラスを介してエンティティを並べ替えようとしていますstd::vector<Entity *>

/*Entity.h*/
class Entity
{
public:
 float x,y;
};

struct compareByX{
 bool operator()(const GameEntity &a, const GameEntity &b)
 {
  return (a.x < b.x);
 }
};   
   
/*Class EntityManager that uses  Entitiy*/

typedef std::vector<Entity *> ENTITY_VECTOR; //Entity reference vector
   
class EntityManager: public Entity
{
private:
 ENTITY_VECTOR managedEntities;

public:
 void sortEntitiesX();
};

void EntityManager::sortEntitiesX()
{
 
 /*perform sorting of the entitiesList by their X value*/
 compareByX comparer;
 
 std::sort(entityList.begin(), entityList.end(), comparer);
}

次のようなエラーが多数発生します

: error: no match for call to '(compareByX) (GameEntity* const&, GameEntity* const&)'
: note: candidates are: bool compareByX::operator()(const GameEntity&, const GameEntity&)

よくわかりませんが、ENTITY_VECTORはですstd::vector<Entity *>。これが、compareByX関数オブジェクトを使用するときに問題になる可能性があるかどうかはわかりません。

私はC++にかなり慣れていないので、どんな種類の助けも歓迎します。

4

6 に答える 6

5

そして3つ目が入ります...質問を編集した後も、まだ1つの未解決のトピックがあります。コンパレータがconst &クラスにGameEntity参加します。の値を操作するには、代わりに引数をvector<GameEntity*>取る必要が あります。const GameEntity*

于 2009-11-19T19:44:43.267 に答える
4

ファンクターはoperator()を定義するクラスであるため、そのクラスのオブジェクトは、関数を呼び出すのと同じ構文で「呼び出す」ことができます。

struct functor { 
   bool operator()(Entity const &a, Entity const &b) {
       return a.x < b.x;
   }
};

これをEntityクラスのメンバーとして使用する場合は、ネストされたクラスを使用します。

class Entity { 
    float x;
public:
    friend class byX;
    class byX {
        bool operator()(Entity const &a, Entity const &b) { 
            return a.x < b.x;
        }
    };
};

次に、ソートは次のようになります。

std::sort(ManagedEndities.begin(), ManagedEntities.end(), Entity::byX());

または、通常エンティティをXで並べ替える場合は、エンティティの演算子<を定義できます。

class Entity { 
     float x;
public:
     bool operator<(Entity const &other) { 
         return x < other.x;
     }
};

この場合、sortの使用は少し簡単になります。

std::sort(ManagedEntities.begin(), ManagedEntities.end());

ただし、Entityクラスの通常のメンバー関数として比較関数を作成すると、かなり醜いソート呼び出しが発生します。通常、ジョブを実行するにはstd::mem_fun_refのようなものが必要になります。それは十分に醜いので、私は一般的に実際のコードではそれを避けます。

于 2009-11-19T19:06:36.010 に答える
2

しかし、最近、この質問を見ました。

答えは次のようなものでした。提供されるsort関数は、何かのメンバー関数であってはなりません。意味:静的関数または自由関数である必要があります。静的関数として宣言する場合でも、Entity::compareByX正しく名前を付けるには、その前に名前を付ける必要があります。

クラス自体で順序を定義する場合、aJがすでに述べたように、関数アダプターを使用するmem_funmem_fun_ref、それを「無料の」ファンクターオブジェクトに注ぐことができます。

Entityオブジェクトに比較を実行させたい場合はsort、オブジェクト(この場合はファンクターまたはコンパレーターと呼ばれます)を提供する必要があります。

struct EntityComp {
  bool operator()( const GameEntity& a, const GameEntity& b ) const { 
    return a.x < b.x;
  }
}


...
std::sort( v.begin(), v.end(), EntityComp() );
于 2009-11-19T18:39:24.490 に答える
1

私はメンバーか湖であるcompareByXべきだと信じていますここを見てくださいstatic

于 2009-11-19T18:45:06.833 に答える
1

「あなたが達成しようとしていること」に照らして、私は別の推測をするかもしれません...あなたはあなたのオブジェクトを彼らのGameEntity::xメンバーによって比較するか、彼らのメンバーによって比較するかを指定できるようにしたいと思いますGameEntity::y

最も簡単な方法は、あなたが行ったように、各メンバーのファンクターを指定することです。

struct CompareX {
   bool operator()( const GameEntity& a, const GameEntity& b ) const {
      return a.x < b.x;
   }
};

struct CompareY {
   bool operator()( const GameEntity& a, const GameEntity& b ) const {
      return a.y < b.y;
   }
};

CompareX compx; // create a compare object
std::sort( v.begin(), v.end(), compx );

「柔軟な」さらに面倒な方法は、テンプレートファンクターを作成することです。

#include <iostream>

using namespace std;

// a mockup of your class
struct GameEntity { float x, y, z; };

// just to be able to print it...
ostream& operator<<( ostream& o, const GameEntity& g ) {
  return o << "(" << g.x << ", " << g.y << ", " << g.z << ")";
}

// cumbersome starts here...
typedef float (GameEntity::*membervar);

// a 'generic' float-member comparator
template< membervar m > struct CompareBy {
   bool operator()( const GameEntity& a, const GameEntity& b ) const {
      return a.*m < b.*m ;
   }
};

// example code
int main() {
   using namespace std;
   GameEntity v[] = { {1,0,0}, {2,0,1}, {3,-1,2} };
   GameEntity* vend = v + sizeof(v)/sizeof(v[0]);

   sort( v, vend, CompareBy< &GameEntity::x >() );
   copy( v, vend, ostream_iterator<GameEntity>( cout, "\n" ) );
}
于 2009-11-19T19:21:38.087 に答える
0

これを試して..

 class CompareByX
 {
   operator ()(const GameEntity &a, const GameEntity &b) { ... };
 };

 ...
 std::sort( this->begin(), this->end(), CompareByX);

一言で言えば、関数は関数オブジェクトです。STLは、指定した2つのパラメーターを受け取る演算子()を具体的に探します。C ++を初めて使用する場合は、演算子とファンクターを調べることをお勧めします。これらは、STLの外部でも非常に便利です。

編集:ジェリーの答えはより良く、より包括的です。

于 2009-11-19T19:09:56.143 に答える