digitalmars.D.learn - Self-referencing template parameters
- Erik Rasmussen <i_am_erik yahoo.com> Mar 20 2006
- Oskar Linde <oskar.lindeREM OVEgmail.com> Mar 20 2006
- Erik Rasmussen <i_am_erik yahoo.com> Mar 20 2006
- Erik Rasmussen <i_am_erik yahoo.com> Mar 20 2006
One way that I have found java's generics to be useful is in doing
something like this:
---
public abstract class Animal<T extends Animal<T>>
{
public abstract T[] procreate(T mate);
}
public class Monkey extends Animal<Monkey>
{
public Monkey[] procreate(Monkey mate)
{
// make sweet monkey love
}
}
---
Although you're not strictly forced to by the compiler, if you make it a
policy to always make your template variable the same as your concrete
subclass, then you have forced any class that extends Animal to provide
a way to "procreate" with its own kind.
I seem to be unable to implement this pattern in D. The following
doesn't work:
---
abstract class Animal(T : Animal!(T))
{
abstract T[] procreate(T mate);
}
---
It doesn't like that template definition on the first line. It says,
"template instance does not match any template declaration".
Any ideas?
Cheers,
Erik
Mar 20 2006
Erik Rasmussen skrev:One way that I have found java's generics to be useful is in doing something like this: --- public abstract class Animal<T extends Animal<T>> { public abstract T[] procreate(T mate); } public class Monkey extends Animal<Monkey> { public Monkey[] procreate(Monkey mate) { // make sweet monkey love } } --- Although you're not strictly forced to by the compiler, if you make it a policy to always make your template variable the same as your concrete subclass, then you have forced any class that extends Animal to provide a way to "procreate" with its own kind. I seem to be unable to implement this pattern in D. The following doesn't work: --- abstract class Animal(T : Animal!(T)) { abstract T[] procreate(T mate); } --- It doesn't like that template definition on the first line. It says, "template instance does not match any template declaration". Any ideas?
The problem is that this line contains a recursive instantiation: abstract class Animal(T : Animal!(T)) Animal!(T) has to be instantiated before the compiler knows how to what type it is. But if you place a static assert in a place outside what the compiler needs to deduce the type: class Animal(T) { this() { static assert(is(T : Animal)); } public abstract T[] procreate(T mate); } Things work as they should. /Oskar
Mar 20 2006
Oskar Linde wrote:The problem is that this line contains a recursive instantiation: abstract class Animal(T : Animal!(T)) Animal!(T) has to be instantiated before the compiler knows how to what type it is. But if you place a static assert in a place outside what the compiler needs to deduce the type: class Animal(T) { this() { static assert(is(T : Animal)); } public abstract T[] procreate(T mate); } Things work as they should. /Oskar
Thanks, but... test.d --- abstract class Animal(T) { this() { static assert(is(T : Animal)); } public abstract T[] procreate(T mate); } class Monkey : Animal!(Monkey) { public Monkey[] procreate(Monkey mate) { return new Monkey[2]; } } int main(char[][] args) { new Monkey(); } --- When I compile, I get: test.d: variable test.Animal!(Monkey).Animal.this.this abstract cannot be applied to variable test.d:3: variable test.Animal!(Monkey).Animal.this.__result abstract cannot be applied to variable Now what? Line 3 is the "this()" line. Erik
Mar 20 2006
Erik Rasmussen wrote:Oskar Linde wrote:The problem is that this line contains a recursive instantiation: abstract class Animal(T : Animal!(T)) Animal!(T) has to be instantiated before the compiler knows how to what type it is. But if you place a static assert in a place outside what the compiler needs to deduce the type: class Animal(T) { this() { static assert(is(T : Animal)); } public abstract T[] procreate(T mate); } Things work as they should. /Oskar
Thanks, but... test.d --- abstract class Animal(T) { this() { static assert(is(T : Animal)); } public abstract T[] procreate(T mate); } class Monkey : Animal!(Monkey) { public Monkey[] procreate(Monkey mate) { return new Monkey[2]; } } int main(char[][] args) { new Monkey(); } --- When I compile, I get: test.d: variable test.Animal!(Monkey).Animal.this.this abstract cannot be applied to variable test.d:3: variable test.Animal!(Monkey).Animal.this.__result abstract cannot be applied to variable Now what? Line 3 is the "this()" line. Erik
Oops. The problem was the "abstract" on the very first line. Bad Java habit. Erik
Mar 20 2006








Erik Rasmussen <i_am_erik yahoo.com>