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