This topic is now archived and is closed to further replies.


A better function object

Recommended Posts

I am a huge proponent of functors, such as Boost''s Function library or Loki''s Functor class. However, both have a glaring flaw: neither one of them overloads operator ==/!=. People attest that it "wouldn''t make sense" but I can think of several places where it would make great sense, such as signals and slots. Lack of operator!= prevents me from allowing users to detach their own events The other complaint is that of technical reasons. Boost uses two separate derived classes to achieve identical behavior on function invocation. I guess they are suggesting that it is difficult to polymorphically compare types. Why not mark operator== a pure virtual function in the base class, and then apply the visitor pattern to call operator== again, this time with the derived type as an argument. If the derived types differ, do not match, then they aren''t equal. If they are, then they can compare the internals. However, this is a pretty simple solution and I''m confident it would have been implemented before if it was this easy. What am I missing? Or do people abstain from implementing this based on reasons of purity?

Share this post

Link to post
Share on other sites
Convince me it''s useful and I''ll add it to Loki (due for an update and release too).

Are we testing for identity or equivalence?
Do we need both?
Any examples of each/either being useful?

Why do you need != to detach?
When you attach, you could return a bread-crumb which is used to remove it. It would be simpler to store the bread-crumb, than hang onto a generalized functor.

Share this post

Link to post
Share on other sites
Functors are meant to insulate clients from the actual function and type (member/free) of function being invoked. They are a type of proxy class. Being as such, I cannot fathom any notion of identity for them, nor a need for it.

I cannot implement an event detach method in my base Event class because of the lack of operator ==/!=. I store a list of functors as event handlers along with the weight. Once I put it in the list, I cannot remove it without testing for equality. This is where equivalence would be make more sense:

#define EventHandler(instance, fn) boost::bind(fn, instance, _1)

// bind gives us a temporary functor that gets copied and added to handlers
// attach is just a insert on a container class with the handler
StartupEvent::attach(EventHandler(this, UserComponent::onStartup));
//...some code
// bind gives us a different temporary functor
StartupEvent::detach(EventHandler(this, UserComponent::onStartup));

If operator== checked identity, then essentially clients would have the tedious task of holding onto the functor they made only so they could remove it. That isn't much better than just giving back a bread crumb, and both bread crumbs/identity semantics of operator== make the same amount of mess in the user's code.

This bugged me initially but I shrugged it off. However when I actually ran into this problem I dug up the CUJ article by Herb Sutter on the subject who provides better explanations and far more compelling reasons than I do.

[edited by - antareus on November 16, 2003 1:31:42 AM]

Share this post

Link to post
Share on other sites