Boost logo

Boost :

From: spam2002_at_[hidden]
Date: 2001-11-17 12:25:11


I would like to use boost::function within a publish-subscribe scheme
as follows (code does not compile):

class ForecastPublisher
{
  public:
    typedef boost::function< void, const std::string & > Subscriber;

    void AddSubscriber( const Subscriber & subscriber );
    void RemoveSubscriber( const Subscriber & subscriber );

    // sends forecast to all currently registered subscribers
    void Publish( const std::string & forecast ) const;

  private:
    // ...
};

void Subscriber1( const std::string & forecast );
void Subscriber2( const std::string & forecast );

int main()
{
  ForecastPublisher publisher;
  publisher.AddSubsriber( &Subscriber1 );
  publisher.Publish( "bla bla" ); // only Subscriber1() is called

  publisher.AddSubscriber( &Subscriber2 );
  // Subscriber1() and Subscriber2() are called
  publisher.Publish( "More bla bla" );

  // AND NOW IT GETS INTERESTING:

  publisher.RemoveSubsriber( &Subscriber1 );
  // only Subscriber2() is called
  publisher.Publish( "More bla bla" );
}

The problem lies in the fact that it is impossible to write
RemoveSubscriber(), because there is no such thing as operator== or
operator!= for two boost::function objects.
Providing equality operators for the current boost::function
implementation does not seem to be possible either, because there is
no way to compare two boost::function objects containing the same
third "foreign" function object:

class MyFunctor
{
  public:
    void operator()() const;

  private:
    // may have state ...
};

int main()
{
  // given that boost::function provides equality operators,
  // how exactly do you implement comparison for f1 and f2?
  // what result should operator== yield in this case? true?
  // false?
  boost::function< void > f1 = MyFunctor();
  boost::function< void > f2 = MyFunctor();

  std::cout << ( f1 == f2 );
}

This fact (and because I think using functors for publish-subscribe
is a good idea) forced me to write my own functor library, which
implements almost the same functionality as boost::function,
boost::bind and boost::mem_fn together (with quite a different
interface though and without providing automatic conversion
from "foreign" functors of course). However, given the low-level
nature of functors implementing them yourself is as undesirable as
writing your own std::vector implementation. This leads to the
following questions:

0. Am I missing something??
1. What was the design rationale behind prefering the possibility to
adapt "foreign" function objects over the possibility to use
boost::function in publish-subscribe schemes? IMHO, the latter is
probably needed by more programmers.
2. As mentioned above, there seems to be no way to extend
boost::function, boost::bind and boost::mem_fn to provide equality
operations AND automatic conversions from "foreign" functors. What's
worse, with equality operations, the functionality of boost::function
and boost::bind seems to be no longer orthogonal. Any ideas anyone?

Regards,

Andreas Huber


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk