aCuria
aCuria

Reputation: 7205

compile error when making functor a class member function

I have a functor which i want to use with sort() the container in question has the type

std::list<std::pair<unsigned, unsigned>>

This container is a temporary initialized in one of class GameBoard's functions.

the functor has the declaration

bool GameBoard::SortMoveList(std::pair<unsigned, unsigned> left, 
                             std::pair<unsigned, unsigned> right)

I get the compile error when i use the functor as follows:

moveList.sort(&GameBoard::SortMoveList);

Error:

1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\list(1324): error C2064: term does not evaluate to a function taking 2 arguments
1>          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\list(1394) : see reference to function template instantiation 'void std::list<_Ty>::merge<_Pr3>(std::list<_Ty> &,_Pr3)' being compiled
1>          with
1>          [
1>              _Ty=std::pair<unsigned int,unsigned int>,
1>              _Pr3=bool (__thiscall GameBoard::* )(std::pair<unsigned int,unsigned int>,std::pair<unsigned int,unsigned int>)
1>          ]
1>          GameBoard.cpp(341) : see reference to function template instantiation 'void std::list<_Ty>::sort<bool(__thiscall GameBoard::* )(std::pair<_Ty1,_Ty2>,std::pair<_Ty1,_Ty2>)>(_Pr3)' being compiled
1>          with
1>          [
1>              _Ty=std::pair<unsigned int,unsigned int>,
1>              _Ty1=unsigned int,
1>              _Ty2=unsigned int,
1>              _Pr3=bool (__thiscall GameBoard::* )(std::pair<unsigned int,unsigned int>,std::pair<unsigned int,unsigned int>)
1>          ]

Any idea whats going wrong here? The functor needs to access the class's private data, so i made it a member fn. If its not a member fn, it compiles fine. How can I solve this problem?

Thanks

Upvotes: 0

Views: 1481

Answers (3)

CashCow
CashCow

Reputation: 31445

You could use that function together with boost::bind.

moveList.sort(boost::bind(&GameBoard::SortMoveList, this, _1, _2 ) );

If your implementation does not require the "this" then (i.e. it does not consult any class members to work out the comparison) then do not make it a class member function (not even a static one).

Note: for boost::bind you might replace with std::bind or std::tr1::bind dependent on what VC10 comes with and that should work.

Upvotes: 1

Loki Astari
Loki Astari

Reputation: 264471

A functor is a an object that behaves like a function.

This means you need to define a class that defines the operator()

Example:

class GameBoardMoveListSorter
{
    bool operator()(std::pair<unsigned, unsigned> const& left, 
                    std::pair<unsigned, unsigned> const& right) const
    {
        return left.first < right.first; // or whatever your strict weak ordering is.
    }
};

/// STUFF

moveList.sort(GameBoardMoveListSorter());

Edit Based on Comment:

Comments from others please:

I though the new standard gave inner classes accesses to the enclosing classes private members. But having just re-read the standard that does not seem to be the wording I am seeing (the behavior of the compiler seems to allow accesses (though I know the conformance in this area has always been weak)).

Section 9.7 Paragraph 4

Like a member function, a friend function (11.4) defined within a nested class is in the lexical scope of that class; it obeys the same rules for name binding as a static member function of that class (9.4), but it has no special access rights to members of an enclosing class.

Based on the above section of the manual. The inner class must be a friend class to accesses the private members of the outer class.

Note. Unlike java there is no implied parent relationship between inner and outer class. Thus the inner class must have an explicit reference to an outer class object to access its members.

#include <memory>

class Chess
{
    private:
        int     board[8][8];


        class GameBoardMoveListSorter
        {
            GameBoardMoveListSorter(Chess& p)
                : parent(p)
            {}

            bool operator()(std::pair<unsigned, unsigned> const& left,
                            std::pair<unsigned, unsigned> const& right) const
            {
                int val = parent.board[0][0] + parent.board[7][7];
                return left.first + val < right.first - val; // or whatever your strict weak ordering is.
            }

            Chess&      parent;
        };
        // I believe that it must be a friend to access private members.
        friend class GameBoardMoveListSorter;

    public:
        void makeMove()
        {
             std::list<std::pair<unsigned, unsigned> >  moveList(/*Generate Moves*/);

             moveList.sort(GameBoardMoveListSorter(*this));
             // Do something with the move list.
        }
};

Upvotes: 2

Puppy
Puppy

Reputation: 146940

You cannot use a member function in this way, as sort() has no notion of the object that it needs to be called upon. As you are in MSVC10, the easiest solution is a lambda.

std::sort(..., [&, this] -> bool (std::pair<unsigned, unsigned> left, std::pair<unsigned, unsigned> right) {
        return this->SortMoveList(left, right);
});

Upvotes: 2

Related Questions