So here's a snippet of my code.
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;
}
}
I'm getting the following error when compiling:
RoutingProtocolImpl.cc:368: error: argument of type bool (RoutingProtocolImpl::)(RoutingProtocolImpl::dv_entry*)' does not match
bool (RoutingProtocolImpl::)(RoutingProtocolImpl::dv_entry)'
The problem is that this:
bool RoutingProtocolImpl::hasInfCost(...)
is a nonstatic member function.It requires an instance of the class to invoke on, ala:
obj->hasInfCost(...)
. However,remove_if
cares not and tries to call it ashasInfCost(...)
. These are incompatible.What you can do is make it
static
:static bool RoutingProtocolImpl::hasInfCost(RoutingProtocolImpl::dv_entry *entry)
This no longer requires an instance of the class to invoke. (It has no member variables, nothis
pointer, etc.). It can be treated as a "normal" function.The Problem
Your predicate
RoutingProtocolImpl::hasInfoCost()
is a member function. The STL algorithms are dumb in that they can only work with things that feel like regular functions. All the STL algorithms that take an operation or a predicate as parameter invoke them like a function:This works fine for function objects, pointers to regular functions and pointers to static members. In the case of member functions of reference objects (objects created on the stack in the algorithm's outer scope) or member functions of pointers to objects the function takes an object to be invoked on:
Now, to resolve the issue you have a number of options.
The Free Function Option
Translate the member function to a free function. If the function needs to work in the context of some object then have that object passed as an extra parameter:
Then, when you pass this function as a reference to an STL algorithm you will have to bind the object parameter:
The Static Member Option
Change the member function so it is a static member function. You can then pass a reference to it with
RoutingProtocolImpl::hasInfoCost
. It would make no sense to have the function accept an extra parameter of the encapsulating class' type. If it needs to work in the context of an object then it shouldn't be static: either transform it to a free function (bound to theRoutingProtocolImpl
visibility constraints, thus promoting decoupling in your code); or take the binder and adapter approach.The Binder and Adapter Option
Use a binder and an adapter from the STL to adapt your member function to something the STL algorithms can work with:
This option is arguably the most flexible option of all. You need not change anything in your code, other than the call to the algorithm. The only drawback is that the call to the algorithm will now look somewhat obscure for the uninitiated.
If you choose this path then make sure you get your const-correctness right: if the member function doesn't need to change the object then mark it as a const function. This way you will be able to invoke it with temporary and const objects that you pass to algorithms.