www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Interfaces and Template Specializations

reply =?ISO-8859-1?Q?Bj=f6rn_T._Herzig?= <raichoo googlemail.com> writes:
Hi,

I've been trying out D lately and stumbled upon the following problem.

I have 2 interfaces:

interface Plugable
{
	public void plug();
}

interface Printable
{
	public void print();
}

and two classes that implement those named Test which implements Plugable and
Printable, and Test2 which only implements Plugable.

I now want to create a generic function with two specializations.

void tester(U)(U u) if (is(U : Plugable) && is(U : Printable))
{
	writefln("U : Printable, Plugable");
	u.plug();
	u.print();
}

void tester(U : Printable)(U u)
{
	writefln("U : printable");
	u.print();
}

First of all this doesn't compile with the dmd 2.014 compiler since it doesn't
accept the if statement after the template declaration (Or did I do something
wrong?). Another thing is that it's really weird syntax. In the second
specialization it's enough to write U : Plugable but it's not possible to write
something like void tester(U : Printable, Plugable)(U u) since Plugable would
be handled as a second template parameter (or am I mistaken?). Wouldn't it be
much nicer if you could write something like this : void tester(U : (Plugable,
Printable))(U u) and void tester(U : (Plugable))(U u)? This way it would be
possible to use a unified syntax for both cases without the need for a special
case with the if-statement.

Btw, are there plans to port dmd to Solaris/OpenSolaris? Since it's my main OS
i would really like to use D on that platform.

Regards,
Björn
Jan 10 2009
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Björn_T._Herzig (raichoo googlemail.com)'s article
 Hi,
 I've been trying out D lately and stumbled upon the following problem.
 I have 2 interfaces:
 interface Plugable
 {
 	public void plug();
 }
 interface Printable
 {
 	public void print();
 }
 and two classes that implement those named Test which implements Plugable and
Printable, and Test2 which only implements Plugable.
 I now want to create a generic function with two specializations.
 void tester(U)(U u) if (is(U : Plugable) && is(U : Printable))
 {
 	writefln("U : Printable, Plugable");
 	u.plug();
 	u.print();
 }
 void tester(U : Printable)(U u)
 {
 	writefln("U : printable");
 	u.print();
 }
 First of all this doesn't compile with the dmd 2.014 compiler since it doesn't
accept the if statement after the template declaration (Or did I do something wrong?). http://digitalmars.com/d/2.0/changelog.html#new2_015 This syntax is called constraints. It didn't exist before 2.015. The info on some pages is outdated. The latest DMD version is 2.023.
 Another thing is that it's really weird syntax. In the second
 specialization it's enough to write U : Plugable but it's not
 possible to write something like void tester(U : Printable, Plugable)(U u)
since
Plugable would be handled as a second template parameter (or am I mistaken?). Wouldn't it be much nicer if you could write something like this : void tester(U : (Plugable, Printable))(U u) and void tester(U : (Plugable))(U u)? This way it would be possible to use a unified syntax for both cases without the need for a special case with the if-statement. The weird syntax is because the first case is a constraint and the second is a template specialization. For consistency, it might be better to just use constraints for everything. Overall, though, D2's compile-time reflection system grew very organically and has a lot of duplicated features. There's been some discussion in the past about how to reduce this complexity by removing redundancy. You may have stumbled on one here: Constraints, as far as I can tell, are just a more general case of template specialization. Maybe we don't need template specialization anymore.
Jan 10 2009
parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sat, Jan 10, 2009 at 5:40 PM, dsimcha <dsimcha yahoo.com> wrote:
 Overall, though, D2's compile-time reflection system grew very organically and
has
 a lot of duplicated features.  There's been some discussion in the past about
how
 to reduce this complexity by removing redundancy.  You may have stumbled on one
 here:  Constraints, as far as I can tell, are just a more general case of
template
 specialization.  Maybe we don't need template specialization anymore.
Not to hijack the thread, but yes - we no longer need template specialization. But we don't necessarily need to kill the syntax, since "template Foo(T: int) {}" is certainly shorter than "template Foo(T) if(is(T: int)) {}". Simply rewrite the former as the latter, problem solved.
Jan 10 2009
prev sibling next sibling parent reply =?ISO-8859-1?Q?Bj=f6rn_T._Herzig?= <raichoo googlemail.com> writes:
dsimcha Wrote:

 == Quote from Björn_T._Herzig (raichoo googlemail.com)'s article
 Hi,
 I've been trying out D lately and stumbled upon the following problem.
 I have 2 interfaces:
 interface Plugable
 {
 	public void plug();
 }
 interface Printable
 {
 	public void print();
 }
 and two classes that implement those named Test which implements Plugable and
Printable, and Test2 which only implements Plugable.
 I now want to create a generic function with two specializations.
 void tester(U)(U u) if (is(U : Plugable) && is(U : Printable))
 {
 	writefln("U : Printable, Plugable");
 	u.plug();
 	u.print();
 }
 void tester(U : Printable)(U u)
 {
 	writefln("U : printable");
 	u.print();
 }
 First of all this doesn't compile with the dmd 2.014 compiler since it doesn't
accept the if statement after the template declaration (Or did I do something wrong?). http://digitalmars.com/d/2.0/changelog.html#new2_015 This syntax is called constraints. It didn't exist before 2.015. The info on some pages is outdated. The latest DMD version is 2.023.
 Another thing is that it's really weird syntax. In the second
 specialization it's enough to write U : Plugable but it's not
 possible to write something like void tester(U : Printable, Plugable)(U u)
since
Plugable would be handled as a second template parameter (or am I mistaken?). Wouldn't it be much nicer if you could write something like this : void tester(U : (Plugable, Printable))(U u) and void tester(U : (Plugable))(U u)? This way it would be possible to use a unified syntax for both cases without the need for a special case with the if-statement. The weird syntax is because the first case is a constraint and the second is a template specialization. For consistency, it might be better to just use constraints for everything. Overall, though, D2's compile-time reflection system grew very organically and has a lot of duplicated features. There's been some discussion in the past about how to reduce this complexity by removing redundancy. You may have stumbled on one here: Constraints, as far as I can tell, are just a more general case of template specialization. Maybe we don't need template specialization anymore.
Thanks, where can I get that version? I'm currently using dmd_2.014-052208_i386.deb from the download page. never saw a newer version. Right now my only possibility to use D is inside of an ubuntu vm which is not really the greatest way... i'd really like to know if dmd will be ported to Solaris. Regards, Björn
Jan 10 2009
next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sat, Jan 10, 2009 at 8:10 PM, Bj=F6rn T. Herzig <raichoo googlemail.com>=
 wrote:
 dsimcha Wrote:

 =3D=3D Quote from Bj=F6rn_T._Herzig (raichoo googlemail.com)'s article
 Hi,
 I've been trying out D lately and stumbled upon the following problem.
 I have 2 interfaces:
 interface Plugable
 {
     public void plug();
 }
 interface Printable
 {
     public void print();
 }
 and two classes that implement those named Test which implements Pluga=
ble and
 Printable, and Test2 which only implements Plugable.
 I now want to create a generic function with two specializations.
 void tester(U)(U u) if (is(U : Plugable) && is(U : Printable))
 {
     writefln("U : Printable, Plugable");
     u.plug();
     u.print();
 }
 void tester(U : Printable)(U u)
 {
     writefln("U : printable");
     u.print();
 }
 First of all this doesn't compile with the dmd 2.014 compiler since it=
doesn't
 accept the if statement after the template declaration (Or did I do some=
thing
 wrong?).

 http://digitalmars.com/d/2.0/changelog.html#new2_015

 This syntax is called constraints.  It didn't exist before 2.015.  The i=
nfo on
 some pages is outdated.  The latest DMD version is 2.023.

 Another thing is that it's really weird syntax. In the second
 specialization it's enough to write U : Plugable but it's not
 possible to write something like void tester(U : Printable, Plugable)(=
U u) since
 Plugable would be handled as a second template parameter (or am I mistak=
en?).
 Wouldn't it be much nicer if you could write something like this : void =
tester(U :
 (Plugable, Printable))(U u) and void tester(U : (Plugable))(U u)? This w=
ay it
 would be possible to use a unified syntax for both cases without the nee=
d for a
 special case with the if-statement.

 The weird syntax is because the first case is a constraint and the secon=
d is a
 template specialization.  For consistency, it might be better to just us=
e
 constraints for everything.

 Overall, though, D2's compile-time reflection system grew very organical=
ly and has
 a lot of duplicated features.  There's been some discussion in the past =
about how
 to reduce this complexity by removing redundancy.  You may have stumbled=
on one
 here:  Constraints, as far as I can tell, are just a more general case o=
f template
 specialization.  Maybe we don't need template specialization anymore.
Thanks, where can I get that version? I'm currently using dmd_2.014-052208_i386.d=
eb from the download page. never saw a newer version. Right now my only pos= sibility to use D is inside of an ubuntu vm which is not really the greates= t way... i'd really like to know if dmd will be ported to Solaris.
 Regards,
 Bj=F6rn
Go to the changelog. http://www.digitalmars.com/d/2.0/changelog.html
Jan 10 2009
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Björn T. Herzig wrote:
 where can I get that version? I'm currently using dmd_2.014-052208_i386.deb
from the download page. never saw a newer version. Right now my only
possibility to use D is inside of an ubuntu vm which is not really the greatest
way... i'd really like to know if dmd will be ported to Solaris.
LDC is the place to look for a Solaris port. I think I recall someone working on an LDC Solaris port, but if that is the case, I think it has not gone very far yet.
Jan 11 2009
prev sibling parent reply =?ISO-8859-1?Q?Bj=f6rn_T._Herzig?= <raichoo googlemail.com> writes:
 Go to the changelog.
 
 http://www.digitalmars.com/d/2.0/changelog.html
Thanks, downloaded the code but my testcode won't compile void tester(U)(U u) if(is(U : Plugable) && is(U : Printable)) { writefln("U : Printable, Plugable"); u.plug(); u.print(); } void tester(U)(U u) { writefln("Nothing"); } When calling tester with an object that implements Plugable and Printable it complains that it matches more than one declaration of the template. Regards, Björn
Jan 10 2009
next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sat, Jan 10, 2009 at 8:51 PM, Bj=F6rn T. Herzig <raichoo googlemail.com>=
 wrote:
 Go to the changelog.

 http://www.digitalmars.com/d/2.0/changelog.html
Thanks, downloaded the code but my testcode won't compile void tester(U)(U u) if(is(U : Plugable) && is(U : Printable))
Try changing this to void tester(U, DUMB=3Dvoid)(U u) if(is(U : Plugable) && is(U : Printable)) stupid compiler.
Jan 10 2009
prev sibling parent reply BCS <ao pathlink.com> writes:
Reply to Björn,

 Go to the changelog.
 
 http://www.digitalmars.com/d/2.0/changelog.html
 
Thanks, downloaded the code but my testcode won't compile void tester(U)(U u) if(is(U : Plugable) && is(U : Printable)) { writefln("U : Printable, Plugable"); u.plug(); u.print(); } void tester(U)(U u) { writefln("Nothing"); } When calling tester with an object that implements Plugable and Printable it complains that it matches more than one declaration of the template. Regards, Björn
try void tester(U)(U u) if(is(U : Plugable) && is(U : Printable)) ... void tester(U)(U u) if(is(U : Plugable) && !is(U : Printable)) ... or void tester(U)(U u) { static if(is(U : Plugable)) u.plug(); static if(is(U : Printable)) u.print(); } or something along that line
Jan 10 2009
parent reply =?ISO-8859-1?Q?Bj=f6rn_T._Herzig?= <raichoo googlemail.com> writes:
BCS Wrote:

 
 try 
 
 void tester(U)(U u) if(is(U : Plugable) && is(U : Printable))
  ...
 void tester(U)(U u) if(is(U : Plugable) && !is(U : Printable))
  ...
 
 or
 
 void tester(U)(U u)
 {
    static if(is(U : Plugable)) u.plug();
    static if(is(U : Printable)) u.print();
 }
 
 or something along that line 
 
 
Thanks, the idea with negating some expressions came to me last night ^^. It works. So that would mean that if i would write something that is more specialized i would have to negate every specialization for the default template? void tester(U)(U u) if (is(U : Plugable) && is(U : Printable)) void tester(U)(U u) if (is(U : Plugable) && !is(U : Printable)) void tester(U)(U u) if (!is(U : Plugable) && is(U : Printable)) void tester(U)(U u) if (is(U : int) && !is(U : Plugable) && !is(U :Printable)) void tester(U)(U u) if (is(U : char) ..........) //default template void tester(U)(U u) if (!is(U : Plugable) && !is(U : Printable) && !is(U : int) && !is(U : char)) etc.... I tried this in a little piece of test code and i need to specialize so much with every specialization i add, that the code becomes very unpleasant to write (see attachment, it won't compile) Regards, Björn
Jan 11 2009
parent Sergey Gromov <snake.scaly gmail.com> writes:
Sun, 11 Jan 2009 07:11:37 -0500, Björn T. Herzig wrote:

 So that would mean that if i would write something that is more
 specialized i would have to negate every specialization for the
 default template?
 
 void tester(U)(U u) if (is(U : Plugable) && is(U : Printable))
 void tester(U)(U u) if (is(U : Plugable) && !is(U : Printable))
 void tester(U)(U u) if (!is(U : Plugable) && is(U : Printable))
 void tester(U)(U u) if (is(U : int) && !is(U : Plugable) && !is(U :Printable))
 void tester(U)(U u) if (is(U : char) ..........)
 //default template
 void tester(U)(U u) if (!is(U : Plugable) && !is(U : Printable) && !is(U :
int) && !is(U : char))
 etc....
 
 I tried this in a little piece of test code and i need to specialize
 so much with every specialization i add, that the code becomes very
 unpleasant to write (see attachment, it won't compile) 
Maybe you should choose a different design then? Use compile-time polymorphism, you seem to do this anyway: class Test { void print() {...} // printable } class Test2 { void print() {...} // printable void plug() {...} // also pluggable } void tester(U)(U u) { static if (!is(typeof(&u.print))) { static assert(false, "non-printable type"); } else { static if (is(typeof(&u.plug))) { u.plug(); } u.print(); } } or maybe use run-time polymorphism--it's hard to tell from this toy case which would be better for the actual task.
Jan 11 2009