On Sun, 25 Mar 2012 18:36:08 -0400, Stewart Gordon <smjg_1...@yahoo.com>
wrote:
I'm coming up against some interesting challenges while porting stuff in
my utility library to D2.
Firstly, D2 uses opBinary and opOpAssign, rather than the
operator-specific op* and op*Assign. While the latter still work, they
aren't mentioned in the current D2 docs. Which would imply that they're
on the way out; however, there's no mention at
https://github.com/D-Programming-Language/d-programming-language.org/blob/master/deprecate.dd
(See also
http://d.puremagic.com/issues/show_bug.cgi?id=7779 )
Still, it seems clear that opBinary/opOpAssign is the D2 way of doing
it. But it has the drawback that, because it's a template, it isn't
virtual. One way about it is to keep the D1-style op functions and make
opUnary/opBinary/opOpAssign call these. But is there a better way?
I have definitely had issues with this. In dcollections, I have versions
of opBinary commented out, because at the time of writing, templates
weren't allowed in the D compiler. I filed this bug:
http://d.puremagic.com/issues/show_bug.cgi?id=4174 Looks like it hasn't
been closed yet...
So for now, I use the undocumented old-style functions. One other thing
that this "wrapper" method loses is covariance, which I use a lot in
dcollections. I haven't filed a bug on it, but there is at least a
workaround on this one -- the template can capture the type of "this" from
the call site as a template parameter.
The other isn't a D2-specific issue, though D2 increases the
significance of it. I have a method with the signature
Set opAnd(bool delegate(Element) dg)
I would like to enable a user of the library to pass in a delegate whose
parameter is any type to which Element is implicitly convertible. This
could be the same type as Element with the top-level constancy changed
(probably the main use case), or a type that is distinct beyond the
constancy level. Turning it into a template
Set opAnd(E)(bool delegate(E) dg)
would address this, but prevent overriding with the appropriate code for
each set implementation.
What I would do is this (assuming template interfaces worked):
Set opAnd(E)(bool delegate(E) dg) if(is(E == Element))
{
// call protected virtual opAnd equivalent which takes delegate of
Element
}
Set opAnd(E)(bool delegate(E) dg) if(!is(E == Element) &&
implicitlyConvertsTo!(E, Element))
{
bool _dg(Element e)
{
return dg(e);
}
// call protected virtual opAnd equivalent with &_dg
}
Note, with proper delegate implicit conversions, you could probably get
some better optimization (including delegates that only differ by const)
by checking if the delegate implicitly converts instead of the element.
-Steve