Re: Getting around the non-virtuality of templates

2012-03-27 Thread Stewart Gordon

On 26/03/2012 14:37, Steven Schveighoffer wrote:
snip

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.


I can't seem to get this to work at the moment:
--
class Base {
T method(T = typeof(this))() {
return this;
}
}

class Derived : Base {}

void main() {
Base b = new Base;
Derived d = new Derived;
auto bm = b.method();
auto dm = d.method();
b = d;
auto dbm = b.method();
pragma(msg, typeof(bm));
pragma(msg, typeof(dm));
pragma(msg, typeof(dbm));
}
--
C:\Users\Stewart\Documents\Programming\D\Testsdmd typeof_this
Base
Base
Base
--

Or do you mean something else?

snip

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
}

snip

I was beginning to think along those lines myself.  I'll try it and see how I 
get on.

Stewart.


Re: Getting around the non-virtuality of templates

2012-03-27 Thread Artur Skawina
On 03/27/12 17:12, Stewart Gordon wrote:
 On 26/03/2012 14:37, Steven Schveighoffer wrote:
 snip
 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.
 
 I can't seem to get this to work at the moment:
 --
 class Base {
 T method(T = typeof(this))() {
 return this;
 }
 }

class Base {
T method(this T)() {
return cast(T)this;
}
}

artur


Re: Getting around the non-virtuality of templates

2012-03-27 Thread Stewart Gordon

On 27/03/2012 16:12, Stewart Gordon wrote:

On 26/03/2012 14:37, Steven Schveighoffer wrote:
snip

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.


I can't seem to get this to work at the moment:

snip

Just figured how to do it.

T method(this T)() {
return cast(T) this;
}

Talk about having not got into D2 programming before

Stewart.


Re: Getting around the non-virtuality of templates

2012-03-27 Thread Steven Schveighoffer
On Tue, 27 Mar 2012 11:26:08 -0400, Stewart Gordon smjg_1...@yahoo.com  
wrote:



On 27/03/2012 16:12, Stewart Gordon wrote:

On 26/03/2012 14:37, Steven Schveighoffer wrote:
snip
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.


I can't seem to get this to work at the moment:

snip

Just figured how to do it.

 T method(this T)() {
 return cast(T) this;
 }

Talk about having not got into D2 programming before


One tip -- if you are doing method as above inside a class and not an  
interface, you can use:


cast(T)cast(void*)this;

which should avoid the unnecessary dynamic cast.  This will *not* work in  
an interface.  I'd argue the compiler should be aware of the special type  
of T for doing casts...


-Steve


Re: Getting around the non-virtuality of templates

2012-03-27 Thread Stewart Gordon

On 27/03/2012 16:46, Steven Schveighoffer wrote:
snip

One tip -- if you are doing method as above inside a class and not an 
interface, you can use:

cast(T)cast(void*)this;

which should avoid the unnecessary dynamic cast.


Which would work if the function always returns this.  But in the general case of what I'm 
using it for, it would call a virtual function that is meant to always return an object of 
the same class as this, but somebody could potentially create a subclass that breaks this 
rule.  But I suppose I could try comparing the .classinfo in an out contract to make sure 
it doesn't happen



This will *not* work in an interface. I'd
argue the compiler should be aware of the special type of T for doing casts...


What's more, given the this T parameter it ought to automatically treat this as being of 
type T within the body of the function.  Essentially, semantically analyse the function 
when instantiated as a method of T rather than as a method of the class in which it is 
actually placed.


Stewart.


Re: Getting around the non-virtuality of templates

2012-03-26 Thread Steven Schveighoffer
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


Getting around the non-virtuality of templates

2012-03-25 Thread Stewart Gordon
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?


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.


Who else has been faced with this problem?  Have you found a good way of 
dealing with it?

Stewart.


Re: Getting around the non-virtuality of templates

2012-03-25 Thread James Miller
On 26 March 2012 11:36, 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?

 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.

 Who else has been faced with this problem?  Have you found a good way of
 dealing with it?

 Stewart.

Non-virtuality of templates is a general problem at the moment.

The issues seem to be around how to handle inheritance of template
arguments, and how to dispatch the functions based on a combination of
template arguments and class hierarchy. This is a hard problem with no
obvious answer.

in terms of trying to work around it, perhaps compile-time reflection
could help, I haven't encountered this before, but that's where I
would start.

--
James Miller


Re: Getting around the non-virtuality of templates

2012-03-25 Thread Simen Kjærås
On Mon, 26 Mar 2012 00:36:08 +0200, 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?


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.


Who else has been faced with this problem?  Have you found a good way of  
dealing with it?


Stewart.


I believe the officially vetted answer is to have the templated calls
forward to virtual functions. Of course, if you need to do something  
specific

before handing it there, you're out of luck.