Boost logo

Boost :

From: Brian McNamara (lorgon_at_[hidden])
Date: 2004-02-28 00:01:57


On Fri, Feb 27, 2004 at 09:07:10PM -0600, Larry Evans wrote:
> On 02/27/2004 04:52 PM, Brian McNamara wrote:
> >>On Thu, Feb 26, 2004 at 12:04:19PM -0600, Larry Evans wrote:
> [snip]
>
> > 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?)
>
> [code snipped]
>
> I'm having a hard time understanding what the code does except what
> amounts to using function pointers (or boost::function objects)
> instead of methods. The code is dynamic because the function pointers
> can be updated at any time. Am I missing something?
>
> I was wanting something more like section 12.7 of _Design&Evolution of
> C++_. At first, I guessed that maybe that's what you were doing, but
> then I wondered why C inherits from B instead of C just contains a B*,
> as in section 12.7.

I was indeed trying to model that example. For those of you without D&E
at hand, here's a slightly-modified version:

   // A stab at delegation that Stroustrup eventually rejected
   class B { int x; void f(int); };
   class C : *p { // delegation-inheritance
      B* p; int y; void g(int);
   };
   void f( C* q ) {
      q->f(3); // automagically means q->p->f(3)
   }

Since there is no such construct in C++, you have to manually write the
call-forwarding routines:

   // actual C++
   class B { int x; void f(int); };
   class C {
      B* p; int y; void g(int); // as before
      void f(int i) { return p->f(i); } // manual delegation
   };

In both cases, "C" can dynamically "change behavior" by changing "p",
and thus delegating the work of "f" to a different "B" object. Note
that the delegate (B) has no way to "get back" to the original object
(C).

You mentioned a couple problems with the regexp code:

> 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).

So I tried to find a solution where you didn't have to write any
call-forwarding routines, and where the delegate doesn't have to store
a pointer back to the original object. I used inheritance to solve one
of the problems (no more need to write a forwarding function: "C"
inherits "f"), and used an explicit extra "self" pointer parameter to
solve the other problem (way to "get back" to the original object) as
well as to recover the information intrinsically lost when switching
from member functions to function objects.

Now "C" can change the "object delegated to" just by assigning a
different delegate object to its own "B" subobject:

   dynamic_cast<B&>(c) = b1; // delegate to b1
   ...
   dynamic_cast<B&>(c) = b2; // delegate to b2

That said, I admit I didn't look very carefully at the regexp code, so
I may be missing some important aspect/intention of what you want to
do with all of this. So let me know, both if my explanation above
clarified what I was trying to do, and if it does or does not
accomplish what you're seeking.

-- 
-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