Forward referencing templates..
Bruno Medeiros
brunodomedeiros+spam at com.gmail
Sun Oct 29 17:07:13 PST 2006
James Dean Palmer wrote:
> I am interested in expressing some data structure relationships like the
> half-edge data structure using templates. For example, consider these
> classes with these type dependencies:
>
> class edge(TFace, TVector) {
> ...
> }
>
> class face(TSurface, TEdge) {
> ...
> }
>
> class surface(TFace) {
> ...
> }
>
> class vector(TNumeric) {
> ...
> }
>
> The idea being any one of these classes could be subclassed - for
> example to represent weighted edges, weighted faces, etc.. Or a
> different kind of basic numeric could be used. Now I would like to say
> this..
>
> alias vector!(double) vector3D;
> alias edge!(face3D, vector3D) edge3D;
> alias face!(surface3D, edge3D) face3D;
> alias surface!(face3D) surface3D;
>
> But I get an error about a forward reference when trying to do it like
> this. C++ has difficulty expressing the same kind of relationship
> because it doesn't forward reference templates. I believe that Java can
> represent this kind of relationship though.
>
> Does anyone know if this can't be done in D? Or is there a better "D"
> way to do it? Thanks!
It's possible, but it's quite hackish. Probably too hackish to be worth
it.To create the equivalent of this:
class Foo(TYPE) { }
alias Foo!(RecursiveFoo) RecursiveFoo;
One has to do this:
--------
import std.stdio;
template Foo_Wrapper(alias SELF_THUNK) {
class Foo() {
alias SELF_THUNK!() SELF;
// SELF is now the current instance of Foo_Wrapper
alias SELF.Foo!() TYPE;
static assert(is(TYPE)); //Ensure entity TYPE is a type
static assert(is(TYPE == Foo)); //Ensure it's the same
void test() {
writefln(typeid(Foo), " ", Foo.mangleof);
writefln(typeid(TYPE), " ", TYPE.mangleof);
}
}
}
template RecursiveFooWrapper_thunk() {
alias RecursiveFoo_Wrapper RecursiveFooWrapper_thunk;
}
// The recursive definition
alias Foo_Wrapper!(RecursiveFooWrapper_thunk) RecursiveFoo_Wrapper;
alias RecursiveFoo_Wrapper.Foo!() RecursiveFoo;
int main() {
RecursiveFoo myfoo = new RecursiveFoo();
myfoo.test();
return 0;
}
--------
Basically to do this, two delayed-evaluation thunks (same as
http://en.wikipedia.org/wiki/Lazy_evaluation) must be created. The first
is RecursiveFooWrapper_thunk, to wrap/delay the recursive alias
parameter. The second one is Foo itself, which is a template ( 'class
Foo()' ) , because inside the immediate body of Foo_Wrapper one cannot
create the instance SELF_THUNK!() , since it gives a recursive error
too. So instead, SELF_THUNK is instanciated inside Foo, after
Foo_Wrapper is successfully instanciated.
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
More information about the Digitalmars-d
mailing list