www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Recursive template instantiation

reply Jack Applegame <japplegame gmail.com> writes:
I'm pretty sure that this code should compile 
(https://dpaste.dzfl.pl/cf1e1ee6ef4b):

struct A(T) {
     ~this() {
         char[T.sizeof] data;
     }
}

struct B(T) {
     A!T foo;
}

struct C {
     B!C bar;
}

void main() {
     C c;
}

But it doesn't:
/d300/f416.d(3): Error: struct f416.C no size because of forward 
reference /d300/f416.d(12): Error: template instance f416.B!(C) 
error instantiating

Notice that the same C++ code compiles without problems:

template<typename T> struct A {
     ~A() {
         char data[sizeof(T)];
     }
};

template<typename T> struct B {
     A<T> foo;
};

struct C {
     B<C> bar;
};

int main() {
     C c;
}

A simple recursion is compiled successfully 
(https://dpaste.dzfl.pl/5a8ff73bfa88):

struct A(T) {
     ~this() {
         char[T.sizeof] data;
     }
}

struct C {
     A!C bar;
}

void main() {
     C c;
}
Mar 13 2017
next sibling parent reply Jack Applegame <japplegame gmail.com> writes:
Is this a bug?
Mar 13 2017
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Monday, 13 March 2017 at 22:05:24 UTC, Jack Applegame wrote:
 Is this a bug?
No it's not struct C { B!C; } is an error. Howto compute C ? <------\ let's check the members; | The member needs a template. | Howto compute the template ? | let's compute the parameters. | What is the first Parameter ? | Its C. | Howoto compute C -------/
Mar 13 2017
parent ag0aep6g <anonymous example.com> writes:
On 03/13/2017 11:58 PM, Stefan Koch wrote:
 On Monday, 13 March 2017 at 22:05:24 UTC, Jack Applegame wrote:
 Is this a bug?
No it's not struct C { B!C; } is an error. Howto compute C ? <------\ let's check the members; | The member needs a template. | Howto compute the template ? | let's compute the parameters. | What is the first Parameter ? | Its C. | Howoto compute C -------/
I don't think that's it. Here's a variant where B is not instantiated with C: ---- struct A() { ~this() { enum s = C.sizeof; } } struct B() { A!() foo; } struct C { B!() bar; } ---- How to compute C? Check members. For member `B!() bar;`, resolve `B!()`. Check members of `B!()`. For member `A!() foo;` resolve `A!()`. Check members of `A!()`. No members => size = 0 (or rather 1, I guess). Bubble up. But the compiler seems to get confused by the destructor. I guess it incorrectly(?) sees a need to analyze C again before it can finish up `A!()`?
Mar 13 2017
prev sibling parent reply ag0aep6g <anonymous example.com> writes:
On 03/13/2017 03:26 PM, Jack Applegame wrote:
 I'm pretty sure that this code should compile
 (https://dpaste.dzfl.pl/cf1e1ee6ef4b):

 struct A(T) {
     ~this() {
         char[T.sizeof] data;
     }
 }

 struct B(T) {
     A!T foo;
 }

 struct C {
     B!C bar;
 }

 void main() {
     C c;
 }

 But it doesn't:
 /d300/f416.d(3): Error: struct f416.C no size because of forward
 reference /d300/f416.d(12): Error: template instance f416.B!(C) error
 instantiating
It compiles when it's a normal method instead of a destructor: ---- struct A(T) { void m() { char[T.sizeof] data; } } /* ... rest as above ... */ ---- I don't see how the destructor makes a difference. Soo, bug?
Mar 13 2017
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Monday, 13 March 2017 at 22:59:36 UTC, ag0aep6g wrote:
 On 03/13/2017 03:26 PM, Jack Applegame wrote:
 I'm pretty sure that this code should compile
 (https://dpaste.dzfl.pl/cf1e1ee6ef4b):

 struct A(T) {
     ~this() {
         char[T.sizeof] data;
     }
 }

 struct B(T) {
     A!T foo;
 }

 struct C {
     B!C bar;
 }

 void main() {
     C c;
 }

 But it doesn't:
 /d300/f416.d(3): Error: struct f416.C no size because of 
 forward
 reference /d300/f416.d(12): Error: template instance 
 f416.B!(C) error
 instantiating
It compiles when it's a normal method instead of a destructor: ---- struct A(T) { void m() { char[T.sizeof] data; } } /* ... rest as above ... */ ---- I don't see how the destructor makes a difference. Soo, bug?
Try to use m.
Mar 13 2017
parent ag0aep6g <anonymous example.com> writes:
On 03/14/2017 12:02 AM, Stefan Koch wrote:
 On Monday, 13 March 2017 at 22:59:36 UTC, ag0aep6g wrote:
[...]
 ----
 struct A(T) {
     void m() {
         char[T.sizeof] data;
     }
 }
 /* ... rest as above ... */
 ----

 I don't see how the destructor makes a difference. Soo, bug?
Try to use m.
Works no problem? ---- struct A(T) { void m() { char[T.sizeof] data; import std.stdio; writeln(T.sizeof); } } struct B(T) { A!T foo; } struct C { B!C bar; } void main() { C c; c.bar.foo.m(); } ---- Prints "1".
Mar 13 2017