0

I have a class based on the code shown here: http://geekswithblogs.net/raccoon_tim/archive/2011/09/28/lambdas-and-events-in-c.aspx

The difference is that I am using variadic templates.

It works well but I can not remove a callback from the vector because I am not able to find it.

Either I am getting an error or I am getting some weird values which I can not compare to find the element.

The code which won't work is:

for (auto i = this->handler.begin(); i != this->handler.end(); i++) {
    if ((*i).target<void(Args...)>() == f.target<void(Args...)>()) {
        this->handler.erase(i);
        break;
    }
}

I googled a lot but I was not able to find anything working for this case. For example std::find does not work in my case.

Any help is appreciated.

Silberling

EDIT: As far as I found out is the major problem that std::function does not support == and != for reasons. Is there a way to get around this? Isn't there a method to identify the lambdas so I cam remove it again? I mean, at least it has a location in memory. .target_type() is another approach which I am trying to find out but it thows some "attempting to reference a deleted function"

Silberling
  • 160
  • 17

1 Answers1

1

Try this: if ((*i).template target<void (T1)>() == f.template target<void (T1)>())

See (probably among others) this question

This should make it compile and work - sort of. Removing functions, lamdbas, other callables is kind of tricky. void(T1) won't work and will always return nullptr on both sides of your comparison.

void(*)(T1) will work, if what you bound with operator += was a free function. It won't work for member functions or lambdas, though.

Even if you find a way to uniquely identify a Callable (I don't know, something silly like storing the typeid().name() and combining it with a its address?), you will still have to store it somewhere to be able to make the call to remove it.

In the future, it would help if you would actually provide your code and errors you were getting, ideally in a Short, Self Contained, Correct (Compilable), Example, for example in a place like this.

Community
  • 1
  • 1
melak47
  • 4,772
  • 2
  • 26
  • 37
  • I think 2) does the trick with: `(*i).template target() == f.template target()` – Banan Nov 04 '14 at 14:36
  • @Banan you're right I misread the documentation on `std::function::target`, it takes a `T`, and returns a `T*` – melak47 Nov 04 '14 at 14:40
  • hmm... after doing some more testing i think your first point is also valid. – Banan Nov 04 '14 at 15:04
  • @Banan Well, I was half-right. `void(T1)` will always return `nullptr`, but `void(*)(T1)` will only work for actual functions, and won't match a lambda with an `operator()`... – melak47 Nov 04 '14 at 15:15
  • Okay. I never knew .template. I tried your code with a little modification because of the variadic template parameter. http://pastebin.com/EpCY9dmJ It compiles but crashes when executed. – Silberling Nov 04 '14 at 17:09
  • The iterator gets invalid. yea -.- – Silberling Nov 04 '14 at 17:15
  • Both sides in this comparison are still 0. I have the same problem as before :-( – Silberling Nov 04 '14 at 17:22
  • @Silberling that's because you can't retrieve the target pointer if the signature you're passing doesn't match - a std::function is not exactly a function pointer – melak47 Nov 11 '14 at 10:41
  • Yeah, thats how I got so far. But isn't there any way to identify them individually? I wrote a test pushing closures, binds and function pointers into it. I think I can identify a closure via .target_type().hash_code(). In my test case that worked. But the same code won't run using function pointers because it is always the same. – Silberling Nov 11 '14 at 11:56
  • What I like to know is why .template target<...>() always returns 0. As the documentations says that happens when "..." does not match. but I don't know what to insert there. When I insert the typedef for the std::function<...> there is should be the same. – Silberling Nov 11 '14 at 11:59
  • @Silberling `target` expects *literally* the type of the target you bound to the std::function. `void(Args...)` will never match the type of anything you passed it, so you get `nullptr`. So if you passed a functor, supply the type of the functor as an argument. If you passed a function(pointer), pass `void(*)(Args...)`. If you passed a bind expression....you're in trouble I guess. [Try this](http://coliru.stacked-crooked.com/a/1423dc2f71f06b65) – melak47 Nov 11 '14 at 16:35