Boost logo

Boost :

From: Brian McNamara (lorgon_at_[hidden])
Date: 2004-02-27 17:52:38


> On Thu, Feb 26, 2004 at 12:04:19PM -0600, Larry Evans wrote:
> > <boost_files>/regexp_first.zip
> > , but I was hoping FC++ could maybe do better. One problem (maybe not
> > too big of a problem) with the regexp_first code is that there's a
> > pointer from subtype to supertype and back (more memory) and the
> > virtual functions in supertype must be delegated to in the subtype
> > (more programmer time).
> >
> > I don't know if FC++ can improve on that, but I'd like to see if it
> > can. Brian, do you have any ideas on how to do it better in FC++?
>
> Brian wrote:
> Sorry, no. Indeed, I cannot imagine _any_ solution in C++ which
> doesn't involve "manually" writing the delegation methods as well as
> keeping pointers in both directions.

I changed my mind, after talking to Yannis about it in front of a white
board. :)

Ok, so you can do something clever with "delegation" or "dynamic
inheritance" or the "state pattern" or whatever you want to call it if
we change the constraints of the problem some. I am still fooling with
the solution, so I'm not sure of all the design constraints yet. I also
want help smoothing it out.

If class "C" wants to delegate method "f" to class B, then below is
code to do it. I used boost::{lambda,function} rather than FC++ in the
example. The basic idea is to get rid of member functions (a recurring
motif) in favor of function objects. Annoyingly, you have to pass a
pointer-to-the-current-object as an extra argument, which I can't seem
to get rid of right now. (Ideas?)

#include <iostream>
using std::cout;
using std::endl;

#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/function.hpp"

using boost::function;
using boost::lambda::_1;
using boost::lambda::_2;
using boost::lambda::constant;

struct B {
   int x;
   function<void(B*,int)> f; // instead of void f(int);
   B( int x_, function<void(B*,int)> f_ ) : x(x_), f(f_) {}
};

struct C : B {
   int y;
   function<void(C*,int)> g; // instead of void g(int);
   C( const B& b, int y_, function<void(C*,int)> g_ )
      : B(b), y(y_), g(g_) {}
};

int main() {
   // make two different Bs with different behavior
   B b1( 1, cout << constant("x is ") << bind(&B::x,_1)
                 << " and arg is " << _2 << "\n" );
   B b2( 2, cout << constant("my x is ") << bind(&B::x,_1)
                 << " and my arg is " << _2 << "\n" );

   // make a C that delegates f() to b1
   C c( b1, 3, cout << constant("y is ") << bind(&C::y,_1)
                    << " and arg is " << _2 << "\n" );

   // the &c extra argument is annoying, grr
   c.f(&c,5);
   c.g(&c,5);

   // now delegate to b2, instead
   dynamic_cast<B&>(c) = b2;
   c.f(&c,5);
   c.g(&c,5);
}

-- 
-Brian McNamara (lorgon_at_[hidden])

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