English 中文(简体)
Declaring function objects for comparison?
原标题:

I have seen other people questions but found none that applied to what I m trying to achieve here.

I m trying to sort Entities via my EntityManager class using std::sort and a 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);
}

I m getting a dozen of errors like

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

I m not sure but ENTITY_VECTOR is std::vector<Entity *> , and I don t know if that could be the problem when using the compareByX function object ?

I m pretty new to C++, so any kind of help is welcome.

最佳回答

And a third one comes in... After you edited you question, still one open topic: your comparator takes a const & to the GameEntity class. It should, in order to work with the values of the vector<GameEntity*>, take const GameEntity* arguments instead.

问题回答

A functor is a class that defines operator() so an object of that class can be "invoked" with the same syntax as calling a function:

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

If you want that as a member of your Entity class, you d use a nested class:

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

Then your sort would look something like this:

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

Alternatively, if you usually sort Entities by X, you could define operator< for Entity:

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

In this case, your use of sort would be a bit simpler:

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

Creating the comparison function as a normal member function of the Entity class, however, will lead to a sort invocation that s pretty ugly -- it ll usually need something like std::mem_fun_ref to do the job; it s sufficiently ugly that I d generally avoid it for real code.

I did see this question, recently, though....

The answer was something in the way of: the function provided to sort should not be a member-function of something. Meaning: it should be a static function, or a free function. In case you declare it a static function, you should still precede it by Entity::compareByX in order to name it correctly.

If you define the order in the class itself, you can, as aJ already said, use a function adapter mem_fun or mem_fun_ref to pour it into a free functor object.

If you want an Entity object to do the comparison, you should provide sort with an object (called a functor or comparator in this case):

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


...
std::sort( v.begin(), v.end(), EntityComp() );

I believe compareByX should be a static member or lake a look here

In the light of what you re trying to achieve , I may do another guess... You want to be able to specify whether to compare your objects by their GameEntity::x member, or by their GameEntity::y member.

The easiest way would be to, as you did, specify a functor for each member:

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

The flexible yet more cumbersome way would be to create a template functor:

#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, "
" ) );
}

try this..

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

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

In a nutshell, a functor is a function object - the STL looks specifically for an operator () that takes in the two parameters I ve specified. If you re new to C++, I suggest you look up operators and functors - they re pretty handy even outside STL.

Edit: Jerry s answer is better, and more comprehensive.





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签