将functor作为类成员函数时编译错误

时间:2011-02-19 18:01:28

标签: c++ visual-studio-2010 stl functor

我有一个仿函数,我想与sort()一起使用,有问题的容器有

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

此容器是在GameBoard类函数之一中初始化的临时容器。

仿函数有声明

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

当我使用仿函数时,我得到编译错误,如下所示:

moveList.sort(&GameBoard::SortMoveList);

错误:

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>          ]

有什么想法在这里出错吗? 仿函数需要访问类的私有数据,所以我把它作为成员fn。如果它不是成员fn,它编译好。我该如何解决这个问题?

由于

3 个答案:

答案 0 :(得分:2)

您不能以这种方式使用成员函数,因为sort()没有需要调用它的对象的概念。正如您在MSVC10中一样,最简单的解决方案是lambda。

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

答案 1 :(得分:2)

仿函数是一个对象,其行为类似于函数。

这意味着您需要定义一个定义operator()

的类

示例:

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

根据评论编辑:

其他人的评论请:

我虽然新标准允许内部类访问封闭类私有成员。但刚刚重新阅读标准似乎不是我所看到的措辞(编译器的行为似乎允许访问(虽然我知道这方面的一致性一直很弱)。)

第9.7节第4段

  

与成员函数一样,嵌套类中定义的友元函数(11.4)位于该类的词法范围内;它遵循与名称绑定相同的规则作为该类的静态成员函数(9.4),但它对封闭类的成员没有特殊的访问权限

基于手册的上述部分。内部类必须是友元类才能访问外部类的私有成员。

请注意。与java不同,内部类和外部类之间没有隐含的父关系。因此,内部类必须具有对外部类对象的显式引用才能访问其成员。

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

答案 2 :(得分:1)

您可以将此功能与boost :: bind一起使用。

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

如果你的实现不需要“this”那么(即它没有咨询任何类成员来计算比较),那么不要把它变成类成员函数(甚至不是静态函数)。

注意:对于boost::bind,您可以替换为std::bindstd::tr1::bind,具体取决于VC10附带的内容,这应该有效。