Ошибка C2064 Visual Studio 2022
Имеется класс SnakeBody, он содержит в функции update использование предиката &SnakeBody::removeTurnsPredicate, которое, содя по всему, не хочет компилироваться. Возникает ошибка: C2064 Результатом вычисления фрагмента не является функция, принимающая 1 аргументов. Вызов turns.erase(remove_if(turns.begin(), turns.end(), &SnakeBody::removeTurnsPredicate), turns.end()); призван удалить нужные элементы в векторе. В чем может быть проблема?:
class SnakeBody: public SnakePart
{
public:
vector<turn> turns;
public:
SnakeBody(String F, float X, float Y, float W, float H) :SnakePart(X, Y, W, H) {
sprite.setTextureRect(IntRect(1 * W, 0 * H, W, H));
sprite.setOrigin(W / 2, H / 2);
};
void update(float time);
bool removeTurnsPredicate(turn turn);
};
Второй:
#include <iostream>
#include <SFML/Graphics.hpp>
#include <list>
using namespace sf;
using namespace std;
class SnakePart
{
public:
float x, y, w, h, dx, dy, speed = 0; //координаты игрока х и у, высота ширина, ускорение (по х и по у), сама скорость
int dir = 0; //направление (direction) движения игрока
float currentFrame = 0;
static String File; //файл с расширением
static Image image;//сфмл изображение
static Texture texture;//сфмл текстура
Sprite sprite;
SnakePart(float X, float Y, float W, float H) { //Конструктор с параметрами(формальными) для класса Player. При создании объекта класса мы будем задавать имя файла, координату Х и У, ширину и высоту
w = W; h = H;//высота и ширина
sprite.setTexture(texture);
x = X; y = Y;//координата появления спрайта
}
static void init();
public:
virtual void update(float time) = 0;
};
struct turn
{
float x, y, speed;
int fromDir, dir;
bool applied;
bool beRemoved;
};
И сам cpp для SnakeBody:
#include "SnakeBody.h"
bool SnakeBody::removeTurnsPredicate(turn turn) {
return turn.beRemoved == true;
}
void SnakeBody::update(float time) {
turns.erase(remove_if(turns.begin(), turns.end(), &SnakeBody::removeTurnsPredicate), turns.end());
switch (dir)
{
case 0: dx = speed; dy = 0; break;
case 1: dx = -speed; dy = 0; break;
case 2: dx = 0; dy = speed; break;
case 3: dx = 0; dy = -speed; break;
}
x += dx;
y += dy;
sprite.setPosition(x, y);
for (auto it = turns.begin(); it != turns.end(); it++) {
if ((it->x == x) && (it->y == y) && (it->applied == false)) {
if ((it->fromDir == 1) && (it->dir == 3)) {
sprite.setTextureRect(IntRect(0 * w, 1 * h, w, h));
}
if ((it->fromDir == 0) && (it->dir == 3)) {
sprite.setTextureRect(IntRect(2 * w, 2 * h, w, h));
}
if ((it->fromDir == 1) && (it->dir == 2)) {
sprite.setTextureRect(IntRect(0 * w, 0 * h, w, h));
}
if ((it->fromDir == 0) && (it->dir == 2)) {
sprite.setTextureRect(IntRect(2 * w, 0 * h, w, h));
}
dir = it->dir;
speed = it->speed;
it->applied = true;
}
if (it->applied == true) {
if ((dir == 0) || (dir == 1)) {
sprite.setTextureRect(IntRect(1 * w, 0 * h, w, h));
}
else
{
sprite.setTextureRect(IntRect(2 * w, 1 * h, w, h));
}
it->beRemoved = true;
}
}
}
Ответы (1 шт):
removeTurnsPredicate - это нестатическая функция-член.
Ее нельзя просто вызвать как обычную функцию: removeTurnsPredicate(x);. Нужно передать объект, на котором вызывать: объект.removeTurnsPredicate(x);. (Внутри class SnakeBody сработает и без объект., но там автоматически добавляется this->.)
std::remove_if не предназначен для таких вызовов. Он не будет добавлять объект. к вызову, и тем более ему негде взять подходящий объект. (Специально упрощаю. &SnakeBody::removeTurnsPredicate - это указатель-на-член, и синтаксис вызова для него - (объект.* &SnakeBody::removeTurnsPredicate)(x);).
Есть несколько вариантов решения:
Сделать
removeTurnsPredicatestatic(или выдвинуть наружу класса), чтобы для его вызова не нужен был экземплярSnakeBody(и заодно поменять параметрconst turn &t- чтобы лишний раз не копировать объекты).Заодно убрать
SnakeBody::, оставить только&removeTurnsPredicate.Вообще убрать
removeTurnsPredicate, вместо него передавать лямбду:remove_if(..., [](const turn &t){return t.beRemoved;}).Использовать
std::mem_fnвместо лямбды:std::mem_fn(&turn::beRemoved). Эффект тот же, но понтов больше.
Ну и turns.erase(remove_if(turns.begin(), turns.end(), /*??*/), turns.end()); можно и нужно сократить до std::erase_if(turns, /*??*/);.