On 2014-03-06 16:48:44 +0000, Steve Teale said:

On Monday, 24 February 2014 at 08:41:06 UTC, Steve Teale wrote:
25 years ago, when I was trying to write some sort of library to go with Walter's C++ compiler, I had a wish, and it still pops into my head from time to time.

What I wanted was functions that were declared in a base class as 'cumulative', or something similar. They would have been generally like virtual functions, except that any derived class that wanted to do something extra - as opposed to something different, would simply define an 'extend', and just specify the extra code. The compiler would then automatically add a call to the same function in whatever base class last defined or extended the method.

OK, I'm back to this because I have done quite a bit of work trying to get to what I wanted. I have converted my app so that it conforms roughly to the above, as a test.

I've also noticed from the responses, and from responses to associated questions, that OOP has become almost a dirty word in the D community. It's old fashioned and slow. So if you're in that camp, you can stop reading now.

I need to handle signals of some sort - let's say just represented by an int.

In my base class I define a method final void handleSignal(int), to which all signals are directed. In the same place there's a virtual function bool signalHandler(int).

The base class also has a data member bool delegate(int)[] handlers.

In classes Base, Intermediate, and Leaf, say, the constructor has a statement:

handlers ~= &Base.signalHandler;
handlers ~= &Intermediate.signalHandler;
handlers ~= &Leaf.signalHandler;

The final handleSignal() method in the base class just traverses the array, calling each delegate in turn until one returns true, and then throws an exception or something if none of them do.

This works nicely. A lot of duplicate code in my original handler functions is eliminated. Any particular leaf class just has to cover the cases peculiar to it's own requirements. Intermediate classes just deal with their generic cases, and the base class handles all the signals that all leaves require.

The compiler doesn't help to ensure that the 'handlers ~=' bit is present in all constructors, so I thought I would be clever, and provide some mixin template or template function that all the constructors in the hierarchy used, so that it was a fairly simple thing to insist on, even if only by example.

But I have been frustrated in this desire. A member function like

final void doMyThing(string CLASSNAME)()
{
    handlers ~= mixin("&"~CLASSNAME~".signalHandler;");
}

defined in the base class does not work, because the compiler complains about the type of the this pointer being Base, despite the fact that I am being explicit about the class name.

Attempts from other directions like calling back down the super() chain don't work because I can't have anything but declarations in a mixin template, and a super() call inside a template function called by the constructor fails because the call is not in a constructor.

Anyone have any bright ideas about how this could be regulated? I can't say forced, because I think the compiler would have to do that.

Steve

I understand what you want to do, I'm just not sure I understand the use-case. However, you may be interested in this code for some ideas for possible alternatives: https://github.com/schancel/gameserver/blob/master/source/connections/igsconnection.d#L148

-S.


Reply via email to