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.