Ошибка find_if: неверная инициализация ссылки типа 'const node&' из выражения типа 'node*'

У меня есть узел структуры:

struct node {
    node *parent;
    int x, y;
    float f, g, h;
    };

Я определяю функцию bool условия предиката следующим образом, чтобы найти, существует ли элемент struct в векторе или нет.

bool Isinit(const node &nm, const node &ref)
{
  if(nm.x==ref.x && nm.y==ref.y)
    return true;
  else
    return false;
}

Тогда я называю функцию следующим образом:

vector<node*>::iterator referIt=find_if (open.begin(), open.end(), Isinit);

Сообщается об ошибке: неверная инициализация ссылки типа 'const node&' из выражения типа 'node*'. Может кто-нибудь объяснить мне ошибку?

2 ответа

Решение

С вашим кодом есть две проблемы: количество аргументов и тип аргумента:

vector<node*>::iterator referIt = 
    find_if (open.begin(), open.end(), Isinit);

bool Isinit(const node &nm, const node &ref);

find_if принимает унарный предикат. Он будет вызывать его для каждого элемента, пока не найдет элемент, для которого предикат возвращает true. Этот предикат должен принимать один аргумент типа, который находится в контейнере. От вашего звонка до find_ifэтот тип node*, Таким образом, ваша подпись должна быть:

bool Isinit(const node* nm);

Теперь это, вероятно, не будет удовлетворять то, что вы хотите сделать, так как вы ищете node* соответствовать вашему refдля этого вам нужно написать функтор:

struct Isinit {
    const node* ref;

    Isinit(const node*);
    bool operator()(const node* nm); // compare passed-in 'nm'
                                     // against member 'ref'
};

И призываем так:

vector<node*>::iterator referIt = 
    find_if (open.begin(), open.end(), Isinit(ref));

Которые, с лямбдами C++11, все могут быть сделаны в строке:

auto referIt = find_if(open.begin(), open.end(), [ref](const node* nm){
    return nm->x == ref->x && nm->y == ref->y;
});

Вот возможная реализация find_if с cppreference.com:

template<class InputIt, class UnaryPredicate>
InputIt find_if(InputIt first, InputIt last, UnaryPredicate p)
{
    for (; first != last; ++first) {
        if (p(*first)) {
            return first;
        }
    }
    return last;
}

Кажется, у вас есть vector из node*Таким образом, когда вы перебираете и разыменовываете итераторы, то, что вы передаете p это node* но не node& элемент. Вы можете изменить свою функцию, чтобы принимать указатели, чтобы решить эту проблему. Кроме того, посмотрите, что find_if реализация принимает UnaryPredicate pтаким образом, вы не можете передать ему функцию, принимающую два аргумента.

Редактировать:

Другая C++11 способ решить эту проблему заключается в использовании bind от functional заголовок и связать ref в Isinit как:

using namespace std::placeholders;
auto referIt = find_if (open.begin(), open.end(), std::bind(Isinit, _1, &ref));
Другие вопросы по тегам