Ошибка компиляции C++ при передаче функции в remove if

вот фрагмент моего кода.


void RoutingProtocolImpl::removeAllInfinity()
{
  dv.erase(std::remove_if(dv.begin(), dv.end(), hasInfCost), dv.end()); 
}

bool RoutingProtocolImpl::hasInfCost(RoutingProtocolImpl::dv_entry *entry)
{
  if (entry->link_cost == INFINITY_COST)
  {
    free(entry);
    return true;
  }
  else
  {
    return false;
  }
}

Я получаю следующую ошибку при компиляции:


RoutingProtocolImpl.cc:368: error: argument of type bool (RoutingProtocolImpl::)(RoutingProtocolImpl::dv_entry*)' does not matchbool (RoutingProtocolImpl::)(RoutingProtocolImpl::dv_entry)'

2 ответов


проблема в том, что это: bool RoutingProtocolImpl::hasInfCost(...) Это нестатическая функция-член.

для этого требуется экземпляр класса для вызова on, ala:obj->hasInfCost(...). Однако,remove_if не заботится и пытается назвать его как hasInfCost(...). Они несовместимы.

что вы можете сделать это static:

static bool RoutingProtocolImpl::hasInfCost(RoutingProtocolImpl::dv_entry *entry) этого больше не требуется экземпляр класса для вызова. (У него нет переменных-членов, нет this указатель и т. д.). Его можно рассматривать как " нормальный" функция.


Проблема

ваш предикат RoutingProtocolImpl::hasInfoCost() - это функция-член. Алгоритмы STL тупы в том, что они могут работать только с вещами, которые кажутся регулярными функциями. Все алгоритмы STL, которые принимают операцию или предикат в качестве параметра, вызывают их как функцию:

op();

это отлично работает для объектов функций, указателей на регулярные функции и указателей на статические члены. В случае функций-членов ссылочных объектов (объектов, созданных на стек во внешней области алгоритма) или функции-члены указателей на объекты функция принимает объект для вызова:

obj.mf();   // reference member function
pobj->mf(); // pointer member function

теперь, чтобы решить эту проблему, у вас есть несколько вариантов.

Опция Свободной Функции

перевести функцию-член в свободную функцию. Если функция должна работать в контексте некоторого объекта, то передайте этот объект в качестве дополнительного параметра:

bool hasInfCost(RoutingProtocolImpl::dv_entry *entry,
                const RoutingProtocolImpl& o);

затем, когда вы передаете эту функцию в качестве ссылки на алгоритм STL вам придется привязать параметр объекта:

for_each(cont.begin(), cont.end(),
         bind2nd(hasInfoCost, RoutingProtocolImpl());

Параметр Статического Члена

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

опция связующего и адаптера

используйте связующее и адаптер из STL для адаптации функции-члена к чему-то, с чем могут работать алгоритмы STL:

dv.erase(remove_if(dv.begin(), dv.end(),
                   bind1st(mem_fun(&RoutingProtocolImpl::hasInfCost),
                           this)),
         dv.end());

этот вариант, возможно, самый гибкий вариант из всех. Вам не нужно ничего менять в коде, кроме вызова алгоритма. Единственным недостатком является то, что вызов алгоритма теперь будет выглядеть несколько неясным для непосвященных.

если вы выберете этот путь, убедитесь, что вы правильно поняли const-correctness: если функция-член не нуждается в изменении объекта, отметьте его как функцию const. Таким образом, Вы сможете вызывать его с временными и const объектами, которые вы передаете алгоритмам.