|
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