Ошибка компиляции 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 match
bool (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 объектами, которые вы передаете алгоритмам.