2012-06-07 2 views
0

Я пытаюсь использовать решение, заданное в this вопрос в классе. Я использовал «remove_if» с предикатной функцией внутри класса.Использование указателя функции предиката внутри класса C++

void classname::function1() 
    { 
    vector<NeighborPoint> neighbors; 
    .... 
    neighbors.erase(std::remove_if(neighbors.begin(),neighbors.end(),&classname::cannotMoveIn), neighbors.end()); 
    ... 
    } 

    bool classname::cannotMoveIn(NeighborPoint mp) 
    { 
     return !mp.inGridNotOccupied; 
    } 

Этот код будет работать, если он не был в классе, и предикат не был функцией-членом. Однако теперь я получаю длинные сообщения об ошибках, которые, как я полагаю, относятся к несовместимости шаблона remove_if с параметром предиката (одна ошибка включает в себя: ошибка C2064: термин не оценивает функцию, принимающую 1 аргумент).

Примечание: Код предназначен для удаления соседних ячеек сетки, которые агент не может перемещать (из 8 возможных ячеек).

Кто-нибудь знает, что не так?

+0

Не должен ли ваш предикат брать «NeighborPoint» в качестве входного параметра? Ваш вектор имеет тип 'NeighborPoint'. Связаны ли «MoorePoint» и «NeighborPoint»? –

+0

Прошу прощения. Я изменил MoorePoint на NeighborPoint, чтобы было ясно, когда вы отправляете здесь, но пропустили этот. – wmac

ответ

1

Этот код будет работать, если он не был в классе, а предикат был не является функцией членом.

Конечно. Метод экземпляра не похож на глобальную функцию; он принимает дополнительный скрытый параметр для this (объект, который он вызывает). Но, похоже, вам не нужно вообще использовать текущий объект в вашей функции. Почему вы сделали это методом экземпляра в первую очередь?

Если вам не нужно использовать this, то одна вещь, которую вы можете сделать, это сделать ее статическим методом (который похож на обычную функцию, за исключением области). Затем вы можете передать его как обычную функцию, как раньше. Еще лучше, чем предикатная функция - использовать объект функции (вам нужно определить класс функтора, который может быть даже вложенным классом, если вы не хотите его перемещать из класса) или лямбда (если у вас есть C++ 11), что позволит предикат быть встроенным в алгоритм удаления и, следовательно, быстрее, чем каждый раз вызывать указатель на функцию.

+0

Спасибо. Действительно, мне нужно было сделать предикатную функцию статической. – wmac

1

Использование std::bind:

neighbors.erase(std::remove_if(neighbors.begin(),neighbors.end(),std::bind(&classname::cannotMoveIn, this, std::placeholders::_1)), neighbors.end()); 

Кроме того, как @Als отметил, что ваш метод classname::cannotMoveIn принимает MoorePoint в качестве аргумента, в то время как ваш вектор содержит NeighborPoint. Обратите внимание, что даже если эти классы связаны, вы срезаете объекты вектора (поскольку вы принимаете аргумент по значению).

Я считаю, что ваш метод должен иметь следующий вид:

bool classname::cannotMoveIn(const NeighborPoint &mp) const; 
+0

Прошу прощения. Я изменил MoorePoint на NeighborPoint, чтобы было ясно, когда вы отправляете здесь, но пропустили этот. – wmac

+0

Отлично, тогда вы все равно должны использовать подпись, предоставленную мной для этого метода. В противном случае вы будете копировать объекты без всякой причины. – mfontanini

+0

Для справки, также можно использовать std: bind1st и std: mem_fun. 'neighbors.erase (std :: remove_if (neighbors.begin(), neighbors.end(), std :: bind1st (std :: mem_fun (& classname :: cannotMoveIn), this)), neighbors.end());' – JsDoITao

Смежные вопросы