1

I have a vector of std::function objects defined like this:

std::vector<std::function<void()>> funcs = { myFunc1, myFunc2, myFunc3 };
//The functions are defined like this:
//void myFunc1() { ... }

I am trying to search through this array for a specific function. My first attempt was using the std::find function, like this:

auto iter = std::find(funcs.begin(), funcs.end(), myFunc2);
//CS2679: binary '==': no operator found which takes a right-hand operator of type '_Ty (__cdecl &)' or there is no acceptable conversion

I learned the hard way that std::function::operator==() does not compare equal unless the function objects are empty (clearly not the case). So I tried using std::find_if to make use of the std::function::target() method:

auto iter = std::find_if(funcs.begin(), funcs.end(), [](const std::function<void()>& f)
    {
        if (*f.target<void()>() == myFunc2)
        //using or not using that '*' before f in the condition makes no difference in the error
            return true;
        return false;
    });

My compiler (VC++ 2019) still complained with the same exact error. Intrigued, I tried writing a find function by hand to see what is happening, but I had no success, got the same error:

auto iter = funcs.begin();
for (; iter != funcs.end(); iter++)
    if (*iter->target<void()>() == myFunc2)
        break;

So here is the question. How can I compare 2 std::function objects to see if they store the same function?

DarkAtom
  • 2,589
  • 1
  • 11
  • 27
  • Does [this](https://en.cppreference.com/w/cpp/utility/functional/function/target) article answer your question? Or do you want to compare them without knowing the type? The latter cannot be done. –  Jun 03 '20 at 19:07
  • @StaceyGirl That is exactly the article I used when first trying to do this. I don't really understand what I am doing wrong (I tried following that example carefully). – DarkAtom Jun 03 '20 at 19:08
  • @AmirKirsh I want to erase the function from the vector (and I am trying to get its iterator position so that I can use `std::vector::erase`) – DarkAtom Jun 03 '20 at 19:10
  • How do you get the function that you want to erase? – Amir Kirsh Jun 03 '20 at 19:11
  • @AmirKirish It have a simple function that takes a function pointer as a parameter and tries to erase it from the vector if it exists. I left that out of the question because I thought the answer would be simpler. – DarkAtom Jun 03 '20 at 19:13
  • Can you store a `pair>` where the int is a "coatcheck" token which is returned when the function is posted, then that coatcheck token can later be used to locate and remove the function? It doesn't need to be fancy, can be a simple monotonically increasing serial number. – Eljay Jun 03 '20 at 21:11

1 Answers1

3

As shown here, template member function target accepts type that is compared with a stored object type. In you case it is a pointer to a function. You have to change

*iter->target<void()>() == myFunc2

to

*iter->target<void(*)()>() == myFunc2

Note that this will only only you to find a plain C function, not an arbitrary callable object (like a lambda function). I think you should consider using plain pointers instead of std::function here.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524