digitalmars.D.learn - Recursive data structure using template won't compile
- Rob T (27/27) Nov 07 2012 I want to create a simple recursive data structure as follows:
- Rob T (5/5) Nov 07 2012 If I use a pointer as the payload type for my d_list, it compiles
- Nick Sabalausky (4/27) Nov 08 2012 Looks like a compiler bug. You should report it:
- Dmitry Olshansky (10/35) Nov 08 2012 Not possible - you don't know the size of R at this point. So determine
- Rob T (18/28) Nov 08 2012 I don't have a nested struct, the struct definition defines the
- Philippe Sigaud (20/48) Nov 08 2012 Rob, your original code:
- Rob T (7/26) Nov 08 2012 Yes that part works fine, but that's only the d_list part. When I
- Rob T (10/42) Nov 08 2012 I want to be clear that I'm trying to define a recursive data
- Manfred Nowak (6/9) Nov 08 2012 A recursive data structure needs a mooring ... and such a mooring is
- Rob T (24/34) Nov 08 2012 I'm afraid I don't follow what you mean by mooring and anchor
- Rob T (20/20) Nov 08 2012 Before I forget, it is important to note that the structure
- Manfred Nowak (32/32) Nov 08 2012 Rob T wrote:
- Manfred Nowak (51/52) Nov 08 2012 `T' was given as:
- Rob T (14/68) Nov 08 2012 I still don't follow what you are trying to point out.
- Manfred Nowak (10/12) Nov 08 2012 .. and if one uses a template one can get an infinite recursion,
- Rob T (15/30) Nov 08 2012 I think I'm starting to understand what you are doing, however
- Nick Sabalausky (5/9) Nov 08 2012 There is no template recursion in your code (you have *exactly* 3
- Nick Sabalausky (48/56) Nov 08 2012 It is *not* the case in his code. He has three actual instantiated
- Rob T (21/69) Nov 08 2012 Nice description!
- Nick Sabalausky (16/26) Nov 08 2012 Historically, DMD tended to have a lot of trouble actually resolving
- Andrej Mitrovic (13/17) Nov 08 2012 Perhaps another possible workaround is to use 'alias this'.
- Rob T (25/25) Nov 08 2012 Interestingly, this is a workaround that may be workable somehow.
- Rob T (10/20) Nov 08 2012 Clearly.
- Manfred Nowak (25/27) Nov 08 2012 This conclusion is wrong. Otherwise one can conclude that `s' is not
- Nick Sabalausky (28/42) Nov 08 2012 Wait a minute, are you or are you not saying that the OP's original
- Manfred Nowak (11/17) Nov 09 2012 That's one correection only. Several more are to come.
- Rob T (13/33) Nov 09 2012 I'm not sure if you commented on why the non-templated version
- Manfred Nowak (6/8) Nov 09 2012 The expectations might be wrong.
- Nick Sabalausky (4/15) Nov 09 2012 One is indeed *able* to do that with templates, but the OP never
- Manfred Nowak (11/12) Nov 10 2012 Please look at the definition of R:
- Nick Sabalausky (29/45) Nov 10 2012 Ok, I see what you're saying, but you're mistaken: That line "d_list!R
- Manfred Nowak (5/6) Nov 11 2012 Thank you. I do recognize now, that my flow of thought stopped
- Rob T (27/37) Nov 09 2012 I agree that you can introduce recursive definitions into a
- Rob T (41/41) Nov 09 2012 If anyone is interested, here's my current work-a-round ...
- Nick Sabalausky (9/19) Nov 09 2012 [...]
- Rob T (5/11) Nov 09 2012 Thanks for filing it.
- Don Clugston (2/12) Nov 12 2012 Yeah. Though note that 1000 bug reports are from bearophile.
- 1100110 (3/4) Nov 12 2012 Well, at least he's persistent.
- Andrej Mitrovic (6/7) Nov 12 2012 Actually only around 300 remain open:
- Andrej Mitrovic (3/7) Nov 12 2012 Oh wait, that's only for DMD. It's 559 in total:
- Rob T (7/16) Nov 12 2012 Issue 8990 and 6969, both related to this thread and unresolved,
- Andrej Mitrovic (9/11) Nov 12 2012 You will need to register, and then use this page:
- Don Clugston (4/22) Nov 13 2012 I recommend deskzilla lite. D is on its list of supported open-source
- Andrej Mitrovic (3/6) Nov 13 2012 Wow, I had no idea they had this. I've added a note about it here:
- Nick Sabalausky (6/10) Nov 13 2012 Awesome! I wish GitHub had something like that. (Hell, I wish every web
- Nick Sabalausky (5/20) Nov 13 2012 Oh, upon using it, it looks like the free version is for OSS projects
- Rob T (5/14) Nov 12 2012 NM, you were talking about bugs reported by bearophile. Back to
- Nick Sabalausky (18/33) Nov 09 2012 But all of the OP's types *do* have a finite length of description.
- Manfred Nowak (3/4) Nov 10 2012 See digitalmars.D.learn:40991
- Rob T (61/61) Nov 08 2012 There is clearly no recursion in the struct, it terminates at the
- Manfred Nowak (14/16) Nov 09 2012 No, they implement not _exactly_ the same structure, because they
- Timon Gehr (3/19) Nov 09 2012 The example definitely exposes a bug in DMD.
- Philippe Sigaud (2/3) Nov 09 2012 Developed in D, I suppose?
- Timon Gehr (2/5) Nov 09 2012 Yes.
- Artur Skawina (3/14) Nov 10 2012 Public? License? URL?
- Manfred Nowak (10/12) Nov 09 2012 May I guess, that your front end is also able to handle this code:
- Timon Gehr (4/16) Nov 09 2012 In theory yes, but it takes a long time and uses a lot of memory,
- Manfred Nowak (16/17) Nov 10 2012 [...]
- Timon Gehr (6/12) Nov 10 2012 In this specific case, yes. But as this is an undecidable property in
- Manfred Nowak (8/9) Nov 10 2012 I do not see, that the compiler has to solve the general case---
- Rob T (29/42) Nov 09 2012 With the unmodified template as posted, I get a very specific
- Manfred Nowak (4/5) Nov 10 2012 I do not see that. Please work on my messages digitalmars.D.learn:40990
- Nick Sabalausky (12/28) Nov 08 2012 That's incorrect behavior. The size of R is NOT needed to determine
- Dmitry Olshansky (59/83) Nov 08 2012 Yeah, that's all good and well, I mean that I can calculate the size.
- Nick Sabalausky (3/6) Nov 08 2012 Right. Point is, it's a compiler bug.
- Rob T (10/16) Nov 08 2012 For D, as opposed to C/C++, my understanding was that specifying
- Manfred Nowak (4/11) Nov 10 2012 I do not see any usage for the member `d_list!R Rlist'.
I want to create a simple recursive data structure as follows: struct R { int value; d_list!R Rlist; } // d-linked list with templated payload struct d_list( T ) { struct node { T payload; node* pred; node* succ; } node* head; node* tail; } The compiler complains about node having "forward references". I was able to get something like this to work in C++, so I imagine I can also get it to work in D, but does anyone know how? I also want to template the recursive structure itself to specify the value type, ie struct R(T){ T value; d_list!R Rlist; }, but I left that out to keep the example more simple. I've been stuck on this problem all day, so any help is appreciated! --rt
Nov 07 2012
If I use a pointer as the payload type for my d_list, it compiles OK. I'd rather not use a pointer for the payload, and it will compile in D if I hard code in the payload type. --rt
Nov 07 2012
On Thu, 08 Nov 2012 07:39:27 +0100 "Rob T" <rob ucora.com> wrote:I want to create a simple recursive data structure as follows: struct R { int value; d_list!R Rlist; } // d-linked list with templated payload struct d_list( T ) { struct node { T payload; node* pred; node* succ; } node* head; node* tail; } The compiler complains about node having "forward references".Looks like a compiler bug. You should report it: http://d.puremagic.com/issues/
Nov 08 2012
11/8/2012 10:39 AM, Rob T пишет:I want to create a simple recursive data structure as follows: struct R { int value; d_list!R Rlist; }Not possible - you don't know the size of R at this point. So determine it compiler looks inside of d_list, and then encounters _node_. It naturally sees T which is R and starts this loop anew. To break this chain make node a separate templated struct outside of d_list. Then peeking inside of d_list compiler shouldn't go crazy.// d-linked list with templated payload struct d_list( T ) { struct node { T payload; node* pred; node* succ; } node* head; node* tail; } The compiler complains about node having "forward references". I was able to get something like this to work in C++, so I imagine I can also get it to work in D, but does anyone know how?Naturally C++ doesn't have nested struct definitions.I also want to template the recursive structure itself to specify the value type, ie struct R(T){ T value; d_list!R Rlist; }, but I left that out to keep the example more simple.I've been stuck on this problem all day, so any help is appreciated!See if it helps. -- Dmitry Olshansky
Nov 08 2012
On Thursday, 8 November 2012 at 15:19:56 UTC, Dmitry Olshansky wrote:Naturally C++ doesn't have nested struct definitions.I don't have a nested struct, the struct definition defines the type only, and the nodes are allocated as pointers from a new operation when the list is composed. The node struct has a member var that may or may not be a struct type, it does not matter, and C++ will allow a member data type to be a struct just fine.I tried moving the node struct outside the d_list struct, but no luck, and I think it should not matter anyway since I can get it to work in that way without a template. The solution so far is to do it the C++ way, using pointers, which sucks. I think in this case the D template should work just fine, and the problem is either a bug or a design flaw with how templates are evaluated. I'll wait a bit longer for more comments before filing a bug report. --rtI also want to template the recursive structure itself to specify the value type, ie struct R(T){ T value; d_list!R Rlist; }, but I left that out to keep the example more simple.I've been stuck on this problem all day, so any help is appreciated!See if it helps.
Nov 08 2012
Rob, your original code: // d-linked list with templated payload struct d_list( T ) { struct node { T payload; node* pred; node* succ; } node* head; node* tail; } compiles just fine for me (Linux 32bits, DMD 2.060). Even with some exercising, the template doesn't fail: void main() { auto list = d_list!(int)(); } On Thu, Nov 8, 2012 at 6:49 PM, Rob T <rob ucora.com> wrote:On Thursday, 8 November 2012 at 15:19:56 UTC, Dmitry Olshansky wrote:Naturally C++ doesn't have nested struct definitions.I don't have a nested struct, the struct definition defines the type only, and the nodes are allocated as pointers from a new operation when the list is composed. The node struct has a member var that may or may not be a struct type, it does not matter, and C++ will allow a member data type to be a struct just fine. I also want to template the recursive structure itself to specify theI tried moving the node struct outside the d_list struct, but no luck, and I think it should not matter anyway since I can get it to work in that way without a template. The solution so far is to do it the C++ way, using pointers, which sucks. I think in this case the D template should work just fine, and the problem is either a bug or a design flaw with how templates are evaluated. I'll wait a bit longer for more comments before filing a bug report. --rtvalue type, ie struct R(T){ T value; d_list!R Rlist; }, but I left that out to keep the example more simple.I've been stuck on this problem all day, so any help is appreciated!See if it helps.
Nov 08 2012
On Thursday, 8 November 2012 at 17:57:11 UTC, Philippe Sigaud wrote:Rob, your original code: // d-linked list with templated payload struct d_list( T ) { struct node { T payload; node* pred; node* succ; } node* head; node* tail; } compiles just fine for me (Linux 32bits, DMD 2.060). Even with some exercising, the template doesn't fail: void main() { auto list = d_list!(int)(); }Yes that part works fine, but that's only the d_list part. When I try to use my supposedly re-usable d-list to define a recursive struct, that's when it fails. Take another look at the original post, you'll see what I mean. --rt
Nov 08 2012
I want to be clear that I'm trying to define a recursive data structure, not a recursive D struct, which of course is not possible. The nodes in the d_list are allocated as pointers, and the node size syhould be knowable during compile time, so this is IMO a design flaw with how templates are being evaluated. It's possible that I'm doing something wrong, so correct me if there's a reasonable way to get this job done (eg no use of mixin hacks). --rt On Thursday, 8 November 2012 at 18:07:45 UTC, Rob T wrote:On Thursday, 8 November 2012 at 17:57:11 UTC, Philippe Sigaud wrote:Rob, your original code: // d-linked list with templated payload struct d_list( T ) { struct node { T payload; node* pred; node* succ; } node* head; node* tail; } compiles just fine for me (Linux 32bits, DMD 2.060). Even with some exercising, the template doesn't fail: void main() { auto list = d_list!(int)(); }Yes that part works fine, but that's only the d_list part. When I try to use my supposedly re-usable d-list to define a recursive struct, that's when it fails. Take another look at the original post, you'll see what I mean. --rt
Nov 08 2012
Rob T wrote:I want to be clear that I'm trying to define a recursive data structure[...]so correct me if there's a reasonable way to get this job doneA recursive data structure needs a mooring ... and such a mooring is missing in the code given. -manfred
Nov 08 2012
On Thursday, 8 November 2012 at 18:45:08 UTC, Manfred Nowak wrote:Rob T wrote:I'm afraid I don't follow what you mean by mooring and anchor given the example at hand. The structure as described allows for the implementation of a real-world useful structure, such as a property tree, where a value may have an associated list of sub-values, (recursive) forming a tree of values. The list of associated values is of arbitrary length and a d-list is not necessarily required, so long as it's a list. This is a simple yet very usefull structure, which I can define apparently legally in D so long as I do not make use of a template. If I can define it legally without a template, then I expected to be able to define it with a template. Obviously infinite recursive structs cannot be allowed, and dmd does detect these cases. In my case, the struct that implements the list contains nothing but pointers, therefore it should allow for lists of lists, and indeed it does, but only if I do not use templates OR I use templates but also change the payload to be a pointer. Why the difference in ability to compile as a template vs a non-template if the all of the template structures can be completely resolved into defined states during compile time - just as it would be if I hard coded the same types? --rtI want to be clear that I'm trying to define a recursive data structure[...]so correct me if there's a reasonable way to get this job doneA recursive data structure needs a mooring ... and such a mooring is missing in the code given. -manfred
Nov 08 2012
Before I forget, it is important to note that the structure consists of two parts, the value with a list of associated sub-values, along with the list. struct R { int value; d_list!R Rlist; } struct d_list( T ) { struct node { T payload; node* pred; node* succ; } node* head; node* tail; } --rt
Nov 08 2012
Rob T wrote: | struct d_list( T ) | { | struct node | { | T payload; | node* pred; | node* succ; | } | node* head; | node* tail; | } This doesn't loo like a list. It looks like the ancor of a list. Let me rewrite it and use D-parlor. | struct Ancor( T){ | struct Node | { | T payload; | Node* pred; | Node* succ; | } | Node* head; | Node* tail; | } This might be the ancor of a doubly linked list for a `payload' of generic type `T'. But there is a problem: generic type `T' might be itself a double linked list using an ancor of type `Ancor'. If this would be true and there would be no mooring everyone, compiler included, would plunge into an infinite loop. Therefore `T' must inform `Ancor' wether that condition comes true---or `T' itself must take the lead. -manfred
Nov 08 2012
Manfred Nowak wrote:or `T' itself must take the lead.`T' was given as: | struct R | { | int value; | d_list!R Rlist; | } ... and using the given changes as well as D-parlor `T' becomes: | struct R { | int value; | Ancor!R list; | } Because `R' can recurse infinitely over `Ancor' a mooring and a way to that mooring is needed. Let the mooring be, when there are no more `Ancor' to expect, i.e. the way to that mooring leads from some height down to zero. That means `R' has to know its height. `R' roughly becomes: | struct R( int height) { | int value; | Ancor!R( height-1) list; | } That describes the way. Of course the mooring is still missing: | struct R( int height) | if( height > 0) { | int value; | Ancor!R( height-1) list; | } | struct R( int height) | if( height <= 0) { | int value; | } That's it. Only missing some testing: import std.stdio: writeln; void main(){ alias R!(1) First; First elem; elem.value= 1; writeln( elem); alias Ancor!First.Node Node; Node n; n.payload= elem; n.pred= null; n.succ= null; writeln( n); alias Ancor!First Ancor1; Ancor1 ancor; ancor.head= &n; ancor.tail= &n; writeln( ancor); } -manfred
Nov 08 2012
On Thursday, 8 November 2012 at 20:39:29 UTC, Manfred Nowak wrote:Manfred Nowak wrote:I still don't follow what you are trying to point out. I use this form of structure in real world applications, and they work just fine as-is. If you mean by 'anchor' a way to end the recursion, that's a trivial problem already solved - the recursion ends when the list is empty. Of course I've left out the associated logic that does the necessary work, since that is not relevant to the problem at hand and clutters the issue. No matter if there's merit to what you are describing, or not, the structure as-is should be legally definable as a template. In fact, I can define the structure just fine provided that I do not use a template. --rtor `T' itself must take the lead.`T' was given as: | struct R | { | int value; | d_list!R Rlist; | } ... and using the given changes as well as D-parlor `T' becomes: | struct R { | int value; | Ancor!R list; | } Because `R' can recurse infinitely over `Ancor' a mooring and a way to that mooring is needed. Let the mooring be, when there are no more `Ancor' to expect, i.e. the way to that mooring leads from some height down to zero. That means `R' has to know its height. `R' roughly becomes: | struct R( int height) { | int value; | Ancor!R( height-1) list; | } That describes the way. Of course the mooring is still missing: | struct R( int height) | if( height > 0) { | int value; | Ancor!R( height-1) list; | } | struct R( int height) | if( height <= 0) { | int value; | } That's it. Only missing some testing: import std.stdio: writeln; void main(){ alias R!(1) First; First elem; elem.value= 1; writeln( elem); alias Ancor!First.Node Node; Node n; n.payload= elem; n.pred= null; n.succ= null; writeln( n); alias Ancor!First Ancor1; Ancor1 ancor; ancor.head= &n; ancor.tail= &n; writeln( ancor); } -manfred
Nov 08 2012
Rob T wrote:In fact, I can define the structure just fine provided that I do not use a template... and if one uses a template one can get an infinite recursion, because templates include recursion. This is the case in your code. The code I gave elimates that infinite recursion. The code compiles although it uses a template. Not seeing e recursion does not mean that there is none. Not every recursion is as simple to see as: | alias X Y; | alias Y X; -manfred
Nov 08 2012
On Thursday, 8 November 2012 at 21:15:17 UTC, Manfred Nowak wrote:Rob T wrote:I think I'm starting to understand what you are doing, however we're operating on two separate planes of existence. What you are describing, is a different structure than what I want. The template creates two separate struct types for R, one with a list and one without (R1 & R2), but I want only one type R, otherwise it will introduce a ton of complications in the form of me having to make just about eveything that uses these two different structures a template and/or duplicated overloaded functions. Perhaps I just don't understand the in's and out's of D templates, but it's just not doing what I want. So is there a way to retain identical struct types for R by disabling the not-so-useful-in-my-case template recursion? --rtIn fact, I can define the structure just fine provided that I do not use a template... and if one uses a template one can get an infinite recursion, because templates include recursion. This is the case in your code. The code I gave elimates that infinite recursion. The code compiles although it uses a template. Not seeing e recursion does not mean that there is none. Not every recursion is as simple to see as: | alias X Y; | alias Y X; -manfred
Nov 08 2012
On Thu, 08 Nov 2012 22:46:46 +0100 "Rob T" <rob ucora.com> wrote:So is there a way to retain identical struct types for R by disabling the not-so-useful-in-my-case template recursion?There is no template recursion in your code (you have *exactly* 3 concrete types even after all template instantiations), see my reply to Manfred.
Nov 08 2012
On Thu, 8 Nov 2012 21:15:17 +0000 (UTC) Manfred Nowak <svv1999 hotmail.com> wrote:Rob T wrote:It is *not* the case in his code. He has three actual instantiated structs: R ------------------ 1. int value (4 bytes) 2. d_list!R Rlist (size: TBD) d_list!R ------------------ // **JUST POINTERS** 1. (d_list!R).node* head (4 bytes, assuming -m32) 2. (d_list!R).node* tail (4 bytes, assuming -m32) (d_list!R).node ------------------ 1. (d_list!R)* outer (4 bytes, assuming -m32) 2. R payload (size: TBD) 3. (d_list!R).node* (4 bytes, assuming -m32) 4. (d_list!R).node* (4 bytes, assuming -m32) What other concrete types are there? *None*. Just those three. Now, let's expand *all* of the aggregate value types: R ------------------ 1. int value (4 bytes) 2. d_list!R Rlist (size: 8 bytes) 2.1. (d_list!R).node* head (4 bytes, assuming -m32) 2.2. (d_list!R).node* tail (4 bytes, assuming -m32) Total: 4+8 == 12 bytes d_list!R ------------------ // *JUST POINTERS* 1. (d_list!R).node* head (4 bytes, assuming -m32) 2. (d_list!R).node* tail (4 bytes, assuming -m32) Total: 4+4 == 8 bytes (d_list!R).node ------------------ 1. (d_list!R)* outer (4 bytes, assuming -m32) 2. R payload (size: 12 bytes) 2.1. int value (4 bytes) 2.2. d_list!R Rlist (size: 8 bytes) 2.2.1. (d_list!R).node* head (4 bytes, assuming -m32) 2.2.2. (d_list!R).node* tail (4 bytes, assuming -m32) 3. (d_list!R).node* (4 bytes, assuming -m32) 4. (d_list!R).node* (4 bytes, assuming -m32) Total: 4+12+4+4 == 24 bytes Now there are NO MORE aggregate types left to be expanded, and ALL 3 types have an exact, FINITE size. There *IS NO RECURSION* here.In fact, I can define the structure just fine provided that I do not use a template... and if one uses a template one can get an infinite recursion, because templates include recursion. This is the case in your code.
Nov 08 2012
On Thursday, 8 November 2012 at 21:47:55 UTC, Nick Sabalausky wrote:It is *not* the case in his code. He has three actual instantiated structs: R ------------------ 1. int value (4 bytes) 2. d_list!R Rlist (size: TBD) d_list!R ------------------ // **JUST POINTERS** 1. (d_list!R).node* head (4 bytes, assuming -m32) 2. (d_list!R).node* tail (4 bytes, assuming -m32) (d_list!R).node ------------------ 1. (d_list!R)* outer (4 bytes, assuming -m32) 2. R payload (size: TBD) 3. (d_list!R).node* (4 bytes, assuming -m32) 4. (d_list!R).node* (4 bytes, assuming -m32) What other concrete types are there? *None*. Just those three. Now, let's expand *all* of the aggregate value types: R ------------------ 1. int value (4 bytes) 2. d_list!R Rlist (size: 8 bytes) 2.1. (d_list!R).node* head (4 bytes, assuming -m32) 2.2. (d_list!R).node* tail (4 bytes, assuming -m32) Total: 4+8 == 12 bytes d_list!R ------------------ // *JUST POINTERS* 1. (d_list!R).node* head (4 bytes, assuming -m32) 2. (d_list!R).node* tail (4 bytes, assuming -m32) Total: 4+4 == 8 bytes (d_list!R).node ------------------ 1. (d_list!R)* outer (4 bytes, assuming -m32) 2. R payload (size: 12 bytes) 2.1. int value (4 bytes) 2.2. d_list!R Rlist (size: 8 bytes) 2.2.1. (d_list!R).node* head (4 bytes, assuming -m32) 2.2.2. (d_list!R).node* tail (4 bytes, assuming -m32) 3. (d_list!R).node* (4 bytes, assuming -m32) 4. (d_list!R).node* (4 bytes, assuming -m32) Total: 4+12+4+4 == 24 bytes Now there are NO MORE aggregate types left to be expanded, and ALL 3 types have an exact, FINITE size. There *IS NO RECURSION* here.Nice description! You have described *exaclty* how I expected the template evaluations to work their way out. I'm very much interested in learning how manfred understands the process will unfold. It could be that the template system simply does not operate as we expect, which IMO would be unfortunate because it will describe a system somewhat unrelated to actual coding (a problem C++ templates are infamous for), or that it is a manifestation of the problem where the out-of-order instantiations are not being evaluated in a way that works for all *legal* cases, which in that case can be considered a bug, esp since D is supposed to allow for out-of-order definitions. Even when we remove the templates, it was noted that it can still fail if the node struct is defined inside the list, but that situation should be easily resolvable. So it seems we have at least one bug, and possibly two, or one bug and a template system that works as expected, but operates in a different dimension. --rt
Nov 08 2012
On Thu, 08 Nov 2012 23:28:05 +0100 "Rob T" <rob ucora.com> wrote:It could be that the template system simply does not operate as we expect, which IMO would be unfortunate because it will describe a system somewhat unrelated to actual coding (a problem C++ templates are infamous for), or that it is a manifestation of the problem where the out-of-order instantiations are not being evaluated in a way that works for all *legal* cases, which in that case can be considered a bug, esp since D is supposed to allow for out-of-order definitions.Historically, DMD tended to have a lot of trouble actually resolving forward references according to spec (perhaps due to it's C/C++ roots?). Most of big glaring problems have been fixed since then, but unfortunately there's still a number of edge cases yet to be ironed out. It *is* possible to construct types in a way that is inherently ambiguous, and cannot be correctly handled by the compiler even in theory. So naturally those cases will end up being "forward reference", or perhaps more accurately "circular definition". But your example is definitely not such a case, so however the compiler is currently processing it, it needs to be fixed. FWIW, you should be able to work around the issue by making some of the pointers "void*". You'll lose some type safety and have to remember to cast things correctly, but it should at least make it compile (although I haven't tried it).
Nov 08 2012
On 11/9/12, Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> wrote:FWIW, you should be able to work around the issue by making some of the pointers "void*". You'll lose some type safety and have to remember to cast things correctly, but it should at least make it compile (although I haven't tried it).Perhaps another possible workaround is to use 'alias this'. struct R { struct Data { int value; } Data data; alias data this; d_list!Data Rlist; } May not work in all cases though..
Nov 08 2012
Interestingly, this is a workaround that may be workable somehow. I've even been able to expand it so that the R.value type is determined by a temnplate. struct node( P ) { P payload; node* pred; node* succ; } struct R( V ) { V value; alias node!R N; d_list!N Rlist; } struct d_list( N ) { N* head; N* tail; // even this works ref typeof(N.payload) getFirstValue(){ return head.payload; } } --rt
Nov 08 2012
On Thursday, 8 November 2012 at 23:05:33 UTC, Nick Sabalausky wrote:Most of big glaring problems have been fixed since then, but unfortunately there's still a number of edge cases yet to be ironed out.Clearly.FWIW, you should be able to work around the issue by making some of the pointers "void*". You'll lose some type safety and have to remember to cast things correctly, but it should at least make it compile (although I haven't tried it).The T* pointers don't seem to be the problem, it's the T payload. If I switch to T* payload it all works OK, but I'll have to perform allocations on each instance of payload which is not desirable. I may still get away with it in my case, but I'm very concerned that it will start eating up memory needlessly because the GC appears to come with a ton of issues yet to be resolved. --rt
Nov 08 2012
Nick Sabalausky wrote:ALL 3 types have an exact, FINITE size. There *IS NO RECURSION* here.This conclusion is wrong. Otherwise one can conclude that `s' is not recursing on itself in this code: struct S{ S* next;} S s; s.next= &s; ... because `s' has a fixed and finite size. One way to see the recursion in the problem given is to evaluate the exact types of the three entities starting with `(d_list!R).(node! R)'---yes, `node' is templated implicitely---and yes, not starting names of types with upper case might confuse the senses. Reaching `R' one might see, that `typeof( R)' must be equal to `typeof( int x &( R x &( (d_list!R).(node!R))^2)^2 )' where `T x U' is equívalent to put types `T' and `U' into a record, `&T' is an adress of some variabkle of type `T' and `T^2' is short hand for `T x T'. If there is no such `R' for which this equality holds, then recursion is not avoidable. Please guess what I believe. -manfred
Nov 08 2012
On Fri, 9 Nov 2012 01:17:09 +0000 (UTC) Manfred Nowak <svv1999 hotmail.com> wrote:Nick Sabalausky wrote:Wait a minute, are you or are you not saying that the OP's original example is impossible (due to recursion)? Because "struct S{ S* next;}" is *not* an example of an impossible data structure. It works perfectly fine because of the indirection introduced by the pointer. The OP's original example is also perfectly possible for the same reason reason as "struct S{ S* next;}". There are two forms of recursion that can render a type impossible: // Recursive data layout: struct S { int i; // <-- Seed S s; // <-- Kaboom! } Or: // Recursive symbols (impossible in D, not sure about ML): alias S!int Foo; // <-- Light the fuse... struct S(T) { S!(typeof(this))* s; // <-- Kaboom! } Neither of those two "bad recursions" occur in the OP's original example. It only has the perfectly benign "struct S{ S* next;}" form of recursion. So the OP is using a perfectly legit, perfectly feasible data structure. DMD just happens to mishandle it and then chokes. So ok: s/There *IS NO RECURSION* here./There is no _IMPOSSIBLE_ recursion here./ALL 3 types have an exact, FINITE size. There *IS NO RECURSION* here.This conclusion is wrong. Otherwise one can conclude that `s' is not recursing on itself in this code: struct S{ S* next;} S s; s.next= &s; ... because `s' has a fixed and finite size.
Nov 08 2012
Nick Sabalausky wrote:So ok: s/There *IS NO RECURSION* here./There is no _IMPOSSIBLE_ recursion here./That's one correection only. Several more are to come. Sorrily no one seems to have recognized this sentence in digitalmars.D.learn:40918:Because `R' can recurse infinitely over `Ancor' a mooring and a way to that mooring is needed.In regex-parlor this meens, that `( R!Ancor!)*' is the type the compiler should be able to handle according to the template definitions given. But the compiler currently can only handle types with a finite length of description on instantiation. For me it is in doubt that this restriction can be declared as a bug. -manfred
Nov 09 2012
On Friday, 9 November 2012 at 14:04:26 UTC, Manfred Nowak wrote:Nick Sabalausky wrote:I'm not sure if you commented on why the non-templated version compiled. Since it does compile as I expected it would, it means that the templates operate in another dimension from what I was expecting, i.e., there's two languages in D, one for templates and another for non-temnplate code. My understanding of D from what I read, was that templates are supposed to work in the same way as regular code. The (T) is only there to introduce a type, so that code can be reused over multiple types. What is happening however, is that the templates are not doing what would be expected if the type was introduced manually, and to me this is plain wrong, or at best very unfortunate for D. --rtSo ok: s/There *IS NO RECURSION* here./There is no _IMPOSSIBLE_ recursion here./That's one correection only. Several more are to come. Sorrily no one seems to have recognized this sentence in digitalmars.D.learn:40918:Because `R' can recurse infinitely over `Ancor' a mooring and a way to that mooring is needed.In regex-parlor this meens, that `( R!Ancor!)*' is the type the compiler should be able to handle according to the template definitions given. But the compiler currently can only handle types with a finite length of description on instantiation. For me it is in doubt that this restriction can be declared as a bug. -manfred
Nov 09 2012
Rob T wrote:What is happening however, is that the templates are not doing what would be expected if the type was introduced manuallyThe expectations might be wrong. With Templates one is able to introduce recursive definitions of types into the type system. As with recursive functions, the feedom, thereby generated, can introduce relaxation as well as strain. -manfred
Nov 09 2012
On Fri, 9 Nov 2012 20:57:42 +0000 (UTC) Manfred Nowak <svv1999 hotmail.com> wrote:Rob T wrote:One is indeed *able* to do that with templates, but the OP never actually did so, so I really don't see the relevance.What is happening however, is that the templates are not doing what would be expected if the type was introduced manuallyThe expectations might be wrong. With Templates one is able to introduce recursive definitions of types into the type system. As with recursive functions, the feedom, thereby generated, can introduce relaxation as well as strain.
Nov 09 2012
Nick Sabalausky wrote:I really don't see the relevancePlease look at the definition of R: struct R { int value; d_list!R Rlist; } If no recursion was wanted the OP should have written: d_list!(R*) Rlist; In digitalmars.D.learn:40990 I already asked for an explanation. -manfred
Nov 10 2012
On Sat, 10 Nov 2012 10:33:39 +0000 (UTC) Manfred Nowak <svv1999 hotmail.com> wrote:Nick Sabalausky wrote:Ok, I see what you're saying, but you're mistaken: That line "d_list!R Rlist;" is not a problematic recursion. Imagine if d_list had been defined like this: struct d_list(T) { int i; } Then would this still be problematic recursion?: struct R { d_list!R Rlist; } No, because R is never actually used anywhere in that d_list (only int is used). In this case, R is nothing more that part of the *name* of a particular instantiation of the d_list template. And indeed, just like the above example, the OP's definition of d_list also does *not* use R: struct d_list( T ) { node* head; node* tail; } Now, yes, that "node" type does use R (instead of R*), *but* "head" and "tail" are merely pointers to "node", so it's ok.I really don't see the relevancePlease look at the definition of R: struct R { int value; d_list!R Rlist; } If no recursion was wanted the OP should have written: d_list!(R*) Rlist;In digitalmars.D.learn:40990 I already asked for an explanation.Actually, my newsreader is kinda shitty, and (AFAIK) doesn't give me any way to lookup a message by ID, so I'm not really sure which message you're referring to :/
Nov 10 2012
Nick Sabalausky wrote:*but* "head" and "tail" are merely pointers to "node"Thank you. I do recognize now, that my flow of thought stopped at the same point at which the flow of control of the compiler stopped. -manfred
Nov 11 2012
On Friday, 9 November 2012 at 20:57:42 UTC, Manfred Nowak wrote:Rob T wrote:I agree that you can introduce recursive definitions into a template, and you have demonstrated that ability rather well, however the definitions in my template does not do this, and so far I have not seen a demonstration of how it could be doing so. The type expansion is definitely finite, there's several posts following through with the expansion, and they all show that the compiler must stop expanding at the pointers. All of the pointers are of a known finite size (standard pointer type) and the type they represent for dereferencing is definitely knowable. The problem appears to be with the compiler failing to evaluate all of the type definitions fully, and as a result it inappropriately fails with a "forwarded reference" error. I've seen a somewhat related problem with functions that return "auto". If the body conatins something that needs to know the return value, the compiler may fail with a "forwarded reference" error. There's absolutely no valid reason why the compiler should be doing this, and it exposes a weakness in the way it does type evaluations (in at least that case). On the other hand, I've seen the compiler do very good work evaluating out-of-order type definitions that are all over the place. If I'm to take the D specification (what little of it there is) at face value, out-of-order type definitions are always perfectly legal provided that they are legal definitions of course, so when the compiler fails on them, then it's a bug that needs to be fixed. --rtWhat is happening however, is that the templates are not doing what would be expected if the type was introduced manuallyThe expectations might be wrong. With Templates one is able to introduce recursive definitions of types into the type system. As with recursive functions, the feedom, thereby generated, can introduce relaxation as well as strain. -manfred
Nov 09 2012
If anyone is interested, here's my current work-a-round ... // original code that fails ... struct R { int value; d_list!R Rlist; } // d-linked list with templated payload struct d_list( T ) { struct node { T payload; node* pred; node* succ; } node* head; node* tail; } // modified code that works ... // no changes made struct R { int value; d_list!R Rlist; } // definition moved out of d_list struct node( T ) { T payload; node* pred; node* succ; } // Added default type N = node!(T) struct d_list( T, N = node!(T) ) { N* head; N* tail; } Thanks again for all your help! --rt
Nov 09 2012
On Sat, 10 Nov 2012 06:29:02 +0100 "Rob T" <rob ucora.com> wrote:If anyone is interested, here's my current work-a-round ... // original code that fails ...[...]// modified code that works ...[...]Thanks again for all your help!I've gone ahead and filed a minimized test case, and also included your workaround: http://d.puremagic.com/issues/show_bug.cgi?id=8990 I didn't make that one struct nested since that's not needed to reproduce the error.
Nov 09 2012
On Saturday, 10 November 2012 at 06:09:41 UTC, Nick Sabalausky wrote:I've gone ahead and filed a minimized test case, and also included your workaround: http://d.puremagic.com/issues/show_bug.cgi?id=8990 I didn't make that one struct nested since that's not needed to reproduce the error.Thanks for filing it. Looking at the bug reports, there's 2000+ unresolved? Yikes. --rt
Nov 09 2012
On 10/11/12 08:53, Rob T wrote:On Saturday, 10 November 2012 at 06:09:41 UTC, Nick Sabalausky wrote:Yeah. Though note that 1000 bug reports are from bearophile.I've gone ahead and filed a minimized test case, and also included your workaround: http://d.puremagic.com/issues/show_bug.cgi?id=8990 I didn't make that one struct nested since that's not needed to reproduce the error.Thanks for filing it. Looking at the bug reports, there's 2000+ unresolved? Yikes. --rt
Nov 12 2012
Yeah. Though note that 1000 bug reports are from bearophile.Well, at least he's persistent. -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Nov 12 2012
On 11/12/12, Don Clugston <dac nospam.com> wrote:Yeah. Though note that 1000 bug reports are from bearophile.Actually only around 300 remain open: http://d.puremagic.com/issues/buglist.cgi?query_format=3Dadvanced&emailrepo= rter2=3D1&emailtype2=3Dsubstring&order=3DImportance&bug_status=3DUNCONFIRME= D&bug_status=3DNEW&bug_status=3DASSIGNED&bug_status=3DREOPENED&bug_status= =3DVERIFIED&email2=3Dbearophile&component=3DDMD&product=3DD
Nov 12 2012
On 11/12/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:On 11/12/12, Don Clugston <dac nospam.com> wrote:Oh wait, that's only for DMD. It's 559 in total: http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&emailreporter2=1&emailtype2=substring&order=Importance&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&email2=bearophileYeah. Though note that 1000 bug reports are from bearophile.Actually only around 300 remain open: http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&emailreporter2=1&emailtype2=substring&order=Importance&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&email2=bearophile
Nov 12 2012
On Monday, 12 November 2012 at 14:28:53 UTC, Andrej Mitrovic wrote:On 11/12/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Issue 8990 and 6969, both related to this thread and unresolved, are not in the list, so I suspect there's a lot more missing too. PS: I could not figure out how to make a useful report using that bug report tool either. --rtOn 11/12/12, Don Clugston <dac nospam.com> wrote:Oh wait, that's only for DMD. It's 559 in total: http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&emailreporter2=1&emailtype2=substring&order=Importance&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&email2=bearophileYeah. Though note that 1000 bug reports are from bearophile.Actually only around 300 remain open: http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&emailreporter2=1&emailtype2=substring&order=Importance&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&email2=bearophile
Nov 12 2012
On 11/13/12, Rob T <rob ucora.com> wrote:PS: I could not figure out how to make a useful report using that bug report tool either.You will need to register, and then use this page: http://d.puremagic.com/issues/enter_bug.cgi?product=D Then select a component (usually DMD, druntime, or Phobos). D2 is selected by default, all that's left is to write a summary and description. You can also click on "Show Advanced Fields" (top left), and in the Keywords field (way down) you can add things like accepts-invalid, or rejects-valid. The list of keywords is here: http://d.puremagic.com/issues/describekeywords.cgi
Nov 12 2012
On 13/11/12 06:51, Rob T wrote:On Monday, 12 November 2012 at 14:28:53 UTC, Andrej Mitrovic wrote:I recommend deskzilla lite. D is on its list of supported open-source projects. It maintains a local copy of the entire bugzilla database, so you're not restricted to the slow and horrible html interface.On 11/12/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Issue 8990 and 6969, both related to this thread and unresolved, are not in the list, so I suspect there's a lot more missing too. PS: I could not figure out how to make a useful report using that bug report tool either. --rtOn 11/12/12, Don Clugston <dac nospam.com> wrote:Oh wait, that's only for DMD. It's 559 in total: http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&emailreporter2=1&emailtype2=substring&order=Importance&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&email2=bearophileYeah. Though note that 1000 bug reports are from bearophile.Actually only around 300 remain open: http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&emailreporter2=1&emailtype2=substring&order=Importance&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&email2=bearophile
Nov 13 2012
On 11/13/12, Don Clugston <dac nospam.com> wrote:I recommend deskzilla lite. D is on its list of supported open-source projects. It maintains a local copy of the entire bugzilla database, so you're not restricted to the slow and horrible html interface.Wow, I had no idea they had this. I've added a note about it here: http://prowiki.org/wiki4d/wiki.cgi?D__Tutorial/BugReports Thanks!
Nov 13 2012
On Tue, 13 Nov 2012 11:56:57 +0100 Don Clugston <dac nospam.com> wrote:I recommend deskzilla lite. D is on its list of supported open-source projects. It maintains a local copy of the entire bugzilla database, so you're not restricted to the slow and horrible html interface.Awesome! I wish GitHub had something like that. (Hell, I wish every web "app" had something like that.) Although, $189 for anything with > 2k issues or anything non-OSS? Geez that's expensive, what are they, Adobe?
Nov 13 2012
On Tue, 13 Nov 2012 11:19:36 -0500 Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> wrote:On Tue, 13 Nov 2012 11:56:57 +0100 Don Clugston <dac nospam.com> wrote:Oh, upon using it, it looks like the free version is for OSS projects with any number of issues *and* non-OSS projects with <= 2k issues. Guess I misread their download page.I recommend deskzilla lite. D is on its list of supported open-source projects. It maintains a local copy of the entire bugzilla database, so you're not restricted to the slow and horrible html interface.Awesome! I wish GitHub had something like that. (Hell, I wish every web "app" had something like that.) Although, $189 for anything with > 2k issues or anything non-OSS? Geez that's expensive, what are they, Adobe?
Nov 13 2012
On Monday, 12 November 2012 at 14:28:53 UTC, Andrej Mitrovic wrote:On 11/12/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:NM, you were talking about bugs reported by bearophile. Back to sleep ... --rtOn 11/12/12, Don Clugston <dac nospam.com> wrote:Oh wait, that's only for DMD. It's 559 in total: http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&emailreporter2=1&emailtype2=substring&order=Importance&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&email2=bearophileYeah. Though note that 1000 bug reports are from bearophile.Actually only around 300 remain open: http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&emailreporter2=1&emailtype2=substring&order=Importance&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=VERIFIED&email2=bearophile
Nov 12 2012
On Fri, 9 Nov 2012 14:04:26 +0000 (UTC) Manfred Nowak <svv1999 hotmail.com> wrote:Sorrily no one seems to have recognized this sentence in digitalmars.D.learn:40918:But all of the OP's types *do* have a finite length of description. I do understand what you are trying to doing with the mooring (although I admit I wasn't familiar with the word "mooring" until this discussion), and I definitely understand what that technique is used for. But it's not relevant to the OP's example, as he's not trying to do anything that for which that "mooring" is actually needed. Note that the following structs do NOT require "mooring" and *already* work perfectly fine with DMD: struct S1 { S1* s; } struct S2(T) { S2!(T)* s; } Those work perfectly fine, even once you actually instantiate S2. The OP's example follows the same pattern as those. If, OTOH, there had been something like this: struct S3(T) { S3!(S3)* s; } Then *that* would require the mooring you described. But the OP was never trying to do anything like that.Because `R' can recurse infinitely over `Ancor' a mooring and a way to that mooring is needed.In regex-parlor this meens, that `( R!Ancor!)*' is the type the compiler should be able to handle according to the template definitions given. But the compiler currently can only handle types with a finite length of description on instantiation. For me it is in doubt that this restriction can be declared as a bug.
Nov 09 2012
Nick Sabalausky wrote:But the OP was never trying to do anything like that.See digitalmars.D.learn:40991 -manfred
Nov 10 2012
There is clearly no recursion in the struct, it terminates at the pointers, therefore it is of finite and knowable size during compile time. R looks like this if value is int dlist!R = struct{ struct*, struct* } R = struct{ int, struct{ struct*, struct* } } node!R = struct{ struct{ int, struct{ struct*, struct* } }, struct*, struct* } The the structs are now fully defined. I will argue that there's actually no recursion in the definition when the definition is looked at from the POV of what the compiler should be seeing. struct R = { int = int; // STOP d_list!R = { node!(R)* = pointer; // STOP node!(R)* = pointer; // STOP } // STOP d_list is now 100% defined We still need to know what node!R is in order to dereference the node!(R)* pointers inside d_list. struct node!(R) = { R = R; // STOP, R is fully defined already. node* = pointer; // STOP node* = pointer; // STOP } // STOP node!(R) is 100% defined. We now know the size and contents of R, d_list!R, and node!R, and we have all the information required to dereference the pointers properly. How is the recursion in the definition stoping the compiler from doing its job? Finally, take note that this altenate recursive definition compiles and works as expected: struct node( P ) { P payload; node* pred; node* succ; } struct R( V ) { V value; alias node!R N; d_list!N Rlist; } struct d_list( N ) { N* head; N* tail; // even this works ref typeof(N.payload) getFirstValue(){ return head.payload; } } The above template definitions define exactly the same structure as the original, it's just done in a different way, by supplying the entire node definition to the d_list instead of just the payload type. Why should this version work and not the other? --rt
Nov 08 2012
Rob T wrote:The above template definitions define exactly the same structure as the originalNo, they implement not _exactly_ the same structure, because they supply more freedom than the original templates version. The original version forced a recursion onto every implementation, whereas this new templates version allows non-recursive implementations. It might be helpfull to reintroduce the forced recursion using the new template definitions. Hint: start with | alias d_list!node00 d_list00; | d_list00 var; and publish whether it is possible to compile this line: | alias R!d_list00 R0; -manfred
Nov 09 2012
On 11/09/2012 02:17 PM, Manfred Nowak wrote:Rob T wrote:The example definitely exposes a bug in DMD. The D front end I am developing can already handle it.The above template definitions define exactly the same structure as the originalNo, they implement not _exactly_ the same structure, because they supply more freedom than the original templates version. The original version forced a recursion onto every implementation, whereas this new templates version allows non-recursive implementations. It might be helpfull to reintroduce the forced recursion using the new template definitions. Hint: start with | alias d_list!node00 d_list00; | d_list00 var; and publish whether it is possible to compile this line: | alias R!d_list00 R0; -manfred
Nov 09 2012
Timon:The D front end I am developing can already handle it.Developed in D, I suppose?
Nov 09 2012
On 11/09/2012 10:24 PM, Philippe Sigaud wrote:Timon: The D front end I am developing can already handle it. Developed in D, I suppose?Yes.
Nov 09 2012
On 11/09/12 23:45, Timon Gehr wrote:On 11/09/2012 10:24 PM, Philippe Sigaud wrote:Public? License? URL? arturTimon: The D front end I am developing can already handle it. Developed in D, I suppose?Yes.
Nov 10 2012
Timon Gehr wrote:The example definitely exposes a bug in DMD. The D front end I am developing can already handle it.May I guess, that your front end is also able to handle this code: struct Elem( size_t myNumber) { Elem!( myNumber +1)* next; } void main(){ Elem!0 list; list.next= new Elem!1; } -manfred
Nov 09 2012
On 11/09/2012 10:32 PM, Manfred Nowak wrote:Timon Gehr wrote:In theory yes, but it takes a long time and uses a lot of memory, especially on a 64 bit build. This is a very different example from the OT's though.The example definitely exposes a bug in DMD. The D front end I am developing can already handle it.May I guess, that your front end is also able to handle this code: struct Elem( size_t myNumber) { Elem!( myNumber +1)* next; } void main(){ Elem!0 list; list.next= new Elem!1; } -manfred
Nov 09 2012
Timon Gehr wrote:In theory yes, but[...] What a pity. Because in the code given only the types Elem!0 and Elem!1 must be indeed initialized. The fact, that the specification of the template describes a family of types with an infinite number of members should not force the front end to check wether all those members are initializable. If the executable is not allowed to build new types, which seems to be canonically, it is sufficient for the front end to check the initializability of those members, for which an initialization is imperative. This polishes my claim in digitalmars.D.learn:40939. For me now it appears as a bug, when the front end assumes, that the executable is allowed to build new types. -manfred
Nov 10 2012
On 11/10/2012 10:12 AM, Manfred Nowak wrote:Timon Gehr wrote:In this specific case, yes. But as this is an undecidable property in general, detecting and exploiting it would merely be an optimization that cannot generally be relied upon. Depending on how powerful it is, it would slow down analysis most of the time. Furthermore, I do not see use cases. I'll look into it when the front end is finished though.In theory yes, but[...] What a pity. Because in the code given only the types Elem!0 and Elem!1 must be indeed initialized. ...
Nov 10 2012
Timon Gehr wrote:But as this is an undecidable property in generalI do not see, that the compiler has to solve the general case--- at least when compiling monolithic code and the executable is only allowed to use types which are initialized at compile time. Upon using several modules the modules might follow some restrictions and I am currently not able to specify that restrictions. -manfred
Nov 10 2012
On Friday, 9 November 2012 at 21:32:01 UTC, Manfred Nowak wrote:Timon Gehr wrote:With the unmodified template as posted, I get a very specific error about "recusive expansion", but I can see why using that form of template - it will expand into multiple types forever Elem!(0), Elem!(1), Elem!(2) ... Elem!(infinity). Now take note that with the modified code below, it works fine, and exactly as I would expect: struct Elem(T) { Elem* next; } My attempt to mess up the compiler did not succeed, the code below still compiles as expected. struct Elem(T) { Elem!(T)* next; } If it works above, then it should also work with the code I introduced in the OP because it's the exact same scenario, only much more simplified. The type expansion should stop at the pointers, and the error message indicates that it does (there's no recursive expansion message), but it fails to evaluate all the types correctly (forwarded reference message). I think this example clears the matter up nicely, and the problem I'm experiencing is definitely a compiler bug. I'd like to see this problem resolved, so I'll file a bug report. BTW, thanks for all the attention to this matter, I've learned a lot more about D templates, such as the recusivness of templates demonstrated by manfred, and the dialogue in here helped me to find a reasonable work-a-round for my particular application. --rtThe example definitely exposes a bug in DMD. The D front end I am developing can already handle it.May I guess, that your front end is also able to handle this code: struct Elem( size_t myNumber) { Elem!( myNumber +1)* next; } void main(){ Elem!0 list; list.next= new Elem!1; } -manfred
Nov 09 2012
Rob T wrote:and the problem I'm experiencing is definitely a compiler bugI do not see that. Please work on my messages digitalmars.D.learn:40990 and digitalmars.D.learn:40991. -manfred
Nov 10 2012
On Thu, 08 Nov 2012 19:19:52 +0400 Dmitry Olshansky <dmitry.olsh gmail.com> wrote:11/8/2012 10:39 AM, Rob T =D0=BF=D0=B8=D1=88=D0=B5=D1=82:That's incorrect behavior. The size of R is NOT needed to determine the size of "d_list!R": Note that "d_list!R" has exactly 2 data members, and BOTH of them are pointers. Therefore, the size of "d_list!R" is trivially determined *regardless* of its template parameter or "nested" type: Two pointers =3D=3D 8 bytes on 32-bit, 16 bytes on 64-bit, *regardless* of what the pointers point to. Also note that "node" is not actually a *data* member of d_list, and does not contribute to the size or internal structure of d_list.I want to create a simple recursive data structure as follows: struct R { int value; d_list!R Rlist; }=20 Not possible - you don't know the size of R at this point. So determine it compiler looks inside of d_list, and then encounters _node_. It naturally sees T which is R and starts this loop anew. =20To break this chain make node a separate templated struct outside of=20 d_list. Then peeking inside of d_list compiler shouldn't go crazy. =20No, I tried that, and it still fails. This is definitely a compiler bug.
Nov 08 2012
11/9/2012 12:35 AM, Nick Sabalausky пишет:On Thu, 08 Nov 2012 19:19:52 +0400 Dmitry Olshansky <dmitry.olsh gmail.com> wrote:Yeah, that's all good and well, I mean that I can calculate the size. But well I'm far smarter then DMD :) And most like the problem is not size. I was mistaken as it must be template instantiation itself. Basically: to analyze R -> inst-te d_list!R ---during which---> (in fact) inst-te node!R ---during which---> inst-te d_list!R -> ... and d_list!R is not yet ready since we analyze node!R Now it could probably improve on it to handle this somehow. I dunno how general it can be or special cased it will be. Now the extra fun - 2 snippets. First one dies with forward ref. Probably because inside of node it issues forward reference to R and inside of R forward reference for d_list and it wasn't finished because of node waiting on forward reference to R? Just coming up with an idea how it may fail, not arguing for it being correct ;) struct d_list { struct node { R payload; node* pred; node* succ; } node* _head; node* _tail; } struct R { int value; d_list Rlist; } void main(){ R r; } But this one doesn't. struct node { R payload; node* pred; node* succ; } struct d_list { node* _head; node* _tail; } struct R { int value; d_list Rlist; } void main(){ R r; } -- Dmitry Olshansky11/8/2012 10:39 AM, Rob T пишет:That's incorrect behavior. The size of R is NOT needed to determine the size of "d_list!R": Note that "d_list!R" has exactly 2 data members, and BOTH of them are pointers. Therefore, the size of "d_list!R" is trivially determined *regardless* of its template parameter or "nested" type: Two pointers == 8 bytes on 32-bit, 16 bytes on 64-bit, *regardless* of what the pointers point to. Also note that "node" is not actually a *data* member of d_list, and does not contribute to the size or internal structure of d_list.I want to create a simple recursive data structure as follows: struct R { int value; d_list!R Rlist; }Not possible - you don't know the size of R at this point. So determine it compiler looks inside of d_list, and then encounters _node_. It naturally sees T which is R and starts this loop anew.
Nov 08 2012
On Fri, 09 Nov 2012 01:26:44 +0400 Dmitry Olshansky <dmitry.olsh gmail.com> wrote:Just coming up with an idea how it may fail, not arguing for it being correct ;)Right. Point is, it's a compiler bug.
Nov 08 2012
On Thursday, 8 November 2012 at 21:50:02 UTC, Nick Sabalausky wrote:On Fri, 09 Nov 2012 01:26:44 +0400 Dmitry Olshansky <dmitry.olsh gmail.com> wrote:For D, as opposed to C/C++, my understanding was that specifying forward references to deal with out-of-order difinitions, or situations like the one I'm experiencing, was not required, so I have to agree it's a "bug" rather than just a limitation of the language and compiler. There's no reason why the compiler should fail in either case, other than due to a less-than-adequate method of evaluating the different structs. --rtJust coming up with an idea how it may fail, not arguing for it being correct ;)Right. Point is, it's a compiler bug.
Nov 08 2012
Rob T wrote:I want to create a simple recursive data structure as follows: struct R { int value; d_list!R Rlist; }I do not see any usage for the member `d_list!R Rlist'. Please explain. -manfred
Nov 10 2012