Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to work around the fact that std::function has no operator==?

Tags:

c++

c++11

Problem: The following code would be very expressive and concise, if not necessarily fast, were it not for the fact that it does not compile.

It does not compile because you cannot compare std::function instances with operator==(). And std::find() tries to do exactly that.

Of course, I could go for an entirely different kind of implementation, but stubborn as I am and fond as I am with the code below, I am looking for something "closest as possible" which works.

Who can provide me a pretty rewrite of the code below which does the same thing?

#include <functional>
#include <vector>

typedef std::function<bool(int)> Tester_t;
typedef std::vector<Tester_t> TesterSet_t;

bool Test(TesterSet_t &candidates, int foo)
{
    TesterSet_t dropouts;
    for( auto& tester : candidates )
    {
        if(!tester(foo))    
        {
            droputs.push_back(tester);
        }
    }

    while(!dropouts.empty())
    {
        // The following line is not compiling because std::function has no operator==()
        TesterSet_t::iterator culprit = 
            std::find( candidates.begin(), candidates.end(), dropouts.back() );
        candidates.erase(culprit);
        dropouts.pop_back();
    }
    return !candidates.empty();
}
like image 830
BitTickler Avatar asked Jan 28 '15 23:01

BitTickler


2 Answers

As others have said, you don't need comparison of std::functions for this. Using standard C++ facilities this can be efficiently (with linear complexity) implemented in two lines:

bool Test(TesterSet_t &candidates, int foo)
{
    candidates.erase(std::remove_if(candidates.begin(), candidates.end(),
        [foo](Tester_t& f){ return !f(foo); }), candidates.end());
    return !candidates.empty();
}
like image 139
Anton Savin Avatar answered Nov 12 '22 01:11

Anton Savin


You don't need equality here. Just erase as you go

for (auto it = candidates.begin(); it != candidates.end(); ) {
    if (! (*it)(foo) ) {
        it = candidates.erase(it);
    }
    else {
        ++it;
    }
}
return !candidates.empty();

This will be also be faster than the version in the question even if operator== was defined for std::function.

like image 25
Barry Avatar answered Nov 12 '22 01:11

Barry