ошибка компиляции при создании функтора функцией-членом класса - PullRequest
0 голосов
/ 19 февраля 2011

У меня есть функтор, который я хочу использовать с 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 ]

2 голосов
/ 19 февраля 2011

Функтор - это объект , который ведет себя как функция.

Это означает, что вам нужно определить класс, который определяет оператор ()

Пример:

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 голосов
/ 19 февраля 2011

Вы не можете использовать функцию-член таким образом, так как sort () не имеет представления об объекте, к которому нужно обращаться. Как и в MSVC10, самое простое решение - лямбда.

std::sort(..., [&, this] -> bool (std::pair<unsigned, unsigned> left, std::pair<unsigned, unsigned> right) {
        return this->SortMoveList(left, right);
});
1 голос
/ 19 февраля 2011

Вы можете использовать эту функцию вместе с boost :: bind.

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

Если ваша реализация не требует «this», то (т.е. она не консультируется ни с одним из членов класса, чтобы выполнить сравнение)тогда не делайте его функцией-членом класса (даже не статической).

Примечание: для boost::bind вы можете заменить на std::bind или std::tr1::bind в зависимости от того, что поставляется с VC10 и что должно работать.

...