How to get around the fact that std :: function does not have an == operator?

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

It does not compile because you cannot compare instances of std :: function with the == () operator. And std :: find () is trying to do just that.

Of course, I could go for a completely different kind of implementation, but stubborn as I am, and I like the way I am with the code below, I am looking for something "as close as possible" that works.

Who can provide me with a pretty rewritten code below that does the same?

#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(); } 
+5
source share
4 answers

As others have said, you do not need to compare std::function to do this. Using standard C ++ tools, this can be effectively (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(); } 
+10
source

Here you do not need equality. 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(); 

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

+2
source

If you never need to remove candidates, you can write:

 bool Test(TesterSet_t &candidates, int foo) { return std::any_of(candidates.begin(), candidates.end(), [&foo](Tester_t &tester) { return tester(foo); }); } 

UPDATE

Ok you need to remove the candidates

 bool Test(TesterSet_t &candidates, int foo) { candidates.erase( std::remove_if(candidates.begin(), candidates.end(), [&foo](Tester_t &tester) { return !tester(foo); }), candidates.end() ); return !candidates.empty(); } 
0
source

The simple answer is not to use std::function<...> in this case, but something like std::function<...> , which defines equality operators. The approach to defining an equality operator for function<...> is to determine, when building, whether the actual functional object really contains the equality operator and, if so, make the object comparable. Otherwise, you would either make a mistake or consider objects containing this type of object of a particular function to be incomparable.

However, direct observation is that most functional objects are not comparable! For example, lambda functions are not comparable, and std::bind() and std::mem_fn() also do not give comparable function objects. Again, a custom implementation may exist for std::bind() and std::mem_fn() . It is impossible to make lambda functions comparable if they do not have an empty capture, in which case they could be turned into pointers to functions and they could be compared.

The implementation of equality function objects is too long to quickly enter an answer. However, you can take a look at my github implementation for comparable comparisons of bind() and mem_fn() . See this answer for a comparable version of the equality std::function<...> . Perhaps it is desirable that the lambda functions are comparable if they have the same signature and all the fixed values ​​are equal to each other.

All of the above, if you can avoid the need, is probably best avoided. However, I came across some use cases where a comparable std::function<...> would be quite convenient, despite its limitations (i.e. not all function objects will be covered).

0
source

Source: https://habr.com/ru/post/1212151/


All Articles