www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - no size yet for forward reference for nested structures

reply "qqiang" <wqzhiep gmail.com> writes:
The following code:
```D
template PowerHeap(T) {
     import std.container : SList;

     private alias PowerForest = SList!PowerNode;

     private final class PowerNode {
         ...
     }

     final class PowerHead {
         ...
     }
}

unittest {
     PowerHeap!int h;
}
```

failed to compile and get the error: PowerHeap!int.PowerNode: no 
size yet for forward reference.

I've googled and found no straightforward solution to this issue. 
The how can I modify my code to eliminate this error?
Jan 13 2015
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
qqiang:

 I've googled and found no straightforward solution to this 
 issue. The how can I modify my code to eliminate this error?
Your code gives me a different error (Error: PowerHeap!int is used as a type). What if you replace the SList with a dynamic array? Bye, bearophile
Jan 14 2015
parent reply "qqiang" <wqzhiep gmail.com> writes:
On Wednesday, 14 January 2015 at 08:31:08 UTC, bearophile wrote:
 qqiang:

 I've googled and found no straightforward solution to this 
 issue. The how can I modify my code to eliminate this error?
Your code gives me a different error (Error: PowerHeap!int is used as a type). What if you replace the SList with a dynamic array? Bye, bearophile
Thanks for your reply. I'm sorry that I've provided wrong code. This is the exact code: ------------------------------------------------------------------- template PowerHeap(T) { import std.container : SList; private alias PowerForest = SList!PowerNode; private final class PowerNode { private { T payload_; uint rank_; PowerForest children_; } } final class PowerHeap { private { PowerNode top_; PowerForest forest_; uint size_; } } } unittest { PowerHeap!int h; } ---------------------------------------------------------------------- My compiler is v2.066.1
Jan 14 2015
parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Wed, 14 Jan 2015 10:41:07 +0000
qqiang via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 template PowerHeap(T) {
      import std.container : SList;
=20
      private alias PowerForest =3D SList!PowerNode;
=20
      private final class PowerNode {
          private {
              T payload_;
              uint rank_;
              PowerForest children_;
          }
      }
=20
      final class PowerHeap {
          private {
              PowerNode top_;
              PowerForest forest_;
              uint size_;
          }
      }
 }
=20
 unittest {
      PowerHeap!int h;
 }
there is a circular dependency in your data structures. you're defining `PowerNode` in the terms of... `PowerNode`. this won't work. your `PowerForest` definition depends of complete `PowerNode` definition, but `PowerNode` definition depends of complete `PowerForest` definition. don't do that.
Jan 14 2015
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 01/14/2015 02:53 AM, ketmar via Digitalmars-d wrote:

 On Wed, 14 Jan 2015 10:41:07 +0000
 qqiang via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 template PowerHeap(T) {
       import std.container : SList;

       private alias PowerForest = SList!PowerNode;

       private final class PowerNode {
           private {
               T payload_;
               uint rank_;
               PowerForest children_;
           }
       }

       final class PowerHeap {
           private {
               PowerNode top_;
               PowerForest forest_;
               uint size_;
           }
       }
 }

 unittest {
       PowerHeap!int h;
 }
there is a circular dependency in your data structures. you're defining `PowerNode` in the terms of... `PowerNode`. this won't work. your `PowerForest` definition depends of complete `PowerNode` definition, but `PowerNode` definition depends of complete `PowerForest` definition. don't do that.
Reduced: import std.container; class Node { SList!Node children; } void main() {} Error: class deneme.Node no size yet for forward reference I wonder why an SList of a reference type requires the size of the elements? The following compiles but is that a pointer to a class variable or a class object? How can we even use the 'children' member? SList!(Node*) children; Ali
Jan 14 2015
next sibling parent reply ketmar via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Wed, 14 Jan 2015 07:09:44 -0800
Ali =C3=87ehreli via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Reduced:
=20
 import std.container;
=20
 class Node
 {
      SList!Node children;
 }
=20
 void main()
 {}
=20
 Error: class deneme.Node no size yet for forward reference
=20
 I wonder why an SList of a reference type requires the size of the=20
 elements? The following compiles but is that a pointer to a class=20
 variable or a class object? How can we even use the 'children' member?
=20
      SList!(Node*) children;
i don't know: i've never used `std.container` anyway. ;-)
Jan 14 2015
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 01/14/2015 07:39 AM, ketmar via Digitalmars-d wrote:
 On Wed, 14 Jan 2015 07:09:44 -0800
 Ali Çehreli via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Reduced:

 import std.container;

 class Node
 {
       SList!Node children;
 }

 void main()
 {}

 Error: class deneme.Node no size yet for forward reference

 I wonder why an SList of a reference type requires the size of the
 elements? The following compiles but is that a pointer to a class
 variable or a class object? How can we even use the 'children' member?

       SList!(Node*) children;
i don't know: i've never used `std.container` anyway. ;-)
It looks like this came up not too long ago: http://forum.dlang.org/thread/akkrerlsjutdfmzswsbo forum.dlang.org#post-akkrerlsjutdfmzswsbo:40forum.dlang.org I think this is a bug but I will wait for others to confirm. Ali
Jan 14 2015
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/14/15 10:09 AM, Ali Çehreli wrote:
 On 01/14/2015 02:53 AM, ketmar via Digitalmars-d wrote:

  > On Wed, 14 Jan 2015 10:41:07 +0000
  > qqiang via Digitalmars-d <digitalmars-d puremagic.com> wrote:
  >
  >> template PowerHeap(T) {
  >>       import std.container : SList;
  >>
  >>       private alias PowerForest = SList!PowerNode;
  >>
  >>       private final class PowerNode {
  >>           private {
  >>               T payload_;
  >>               uint rank_;
  >>               PowerForest children_;
  >>           }
  >>       }
  >>
  >>       final class PowerHeap {
  >>           private {
  >>               PowerNode top_;
  >>               PowerForest forest_;
  >>               uint size_;
  >>           }
  >>       }
  >> }
  >>
  >> unittest {
  >>       PowerHeap!int h;
  >> }
  > there is a circular dependency in your data structures. you're defining
  > `PowerNode` in the terms of... `PowerNode`. this won't work.
  >
  > your `PowerForest` definition depends of complete `PowerNode`
  > definition, but `PowerNode` definition depends of complete
  > `PowerForest` definition.
  >
  > don't do that.
  >

 Reduced:

 import std.container;

 class Node
 {
      SList!Node children;
 }

 void main()
 {}

 Error: class deneme.Node no size yet for forward reference

 I wonder why an SList of a reference type requires the size of the
 elements? The following compiles but is that a pointer to a class
 variable or a class object? How can we even use the 'children' member?

      SList!(Node*) children;

 Ali
In my not-so-expert opinion, I think this is somewhat of a bug, but not in the compiler. Note that it depends heavily on the definition of SList. If SList starts using pieces of S, it may confuse or create issues with the compiler. A simple test is to declare an opaque class: class S; void main() { S foo; } This works (at least it works to compile, not to link as the linker can't find the class symbol) Now, if I do this: import std.container; class S; alias listofs = SList!S; void main() { S foo; } I get the following audit from the compiler: /usr/share/dmd/src/phobos/std/traits.d(2032): Error: class testforward.S unknown size /usr/share/dmd/src/phobos/std/traits.d(2198): Error: template instance std.traits.FieldTypeTuple!(S) error instantiating /usr/share/dmd/src/phobos/std/traits.d(2349): instantiated from here: RepresentationTypeTuple!(S) /usr/share/dmd/src/phobos/std/traits.d(2692): instantiated from here: hasRawAliasing!(S) /usr/share/dmd/src/phobos/std/algorithm.d(1888): instantiated from here: hasAliasing!(S) /usr/share/dmd/src/phobos/std/container.d(1008): Error: template instance std.algorithm.move!(S) error instantiating testforward.d(4): instantiated from here: SList!(S) /usr/share/dmd/src/phobos/std/range.d(3149): Error: template instance std.range.hasAssignableElements!(Range) error instantiating /usr/share/dmd/src/phobos/std/container.d(1359): Error: template instance std.range.Take!(Range) error instantiating testforward.d(4): instantiated from here: SList!(S) So I think it's SList's invocation of move, which in turn checks hasAliasing, which in turn needs S's total definition (as it starts getting the fields of S). I think hasAliasing!(someclass) needs to be short circuited to true, or slist needs to use some other mechanism. I don't know how SList works exactly, maybe it does not actually allocate a list of class references, but instead emplaces them. In that case, you may be out of luck. -Steve
Jan 15 2015
parent reply zeljkog <zeljkog home.com> writes:
This compiles:

import std.container;

class Node
{
   DList!Node children;
}
Jan 15 2015
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 01/15/2015 06:56 AM, zeljkog wrote:
 This compiles:

 import std.container;

 class Node
 {
     DList!Node children;
 }
So does using an 'interface', which may be more desirable in some cases: import std.container; interface Iface {} class Node : Iface { SList!Iface children; } void main() { auto n = new Node(); } Ali
Jan 15 2015
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/15/15 9:56 AM, zeljkog wrote:
 This compiles:

 import std.container;

 class Node
 {
     DList!Node children;
 }
Then use DList? DList is not SList, they were written by different people. -Steve
Jan 15 2015
parent reply zeljkog <zeljkog home.com> writes:
On 15.01.15 23:30, Steven Schveighoffer wrote:
 On 1/15/15 9:56 AM, zeljkog wrote:
 This compiles:

 import std.container;

 class Node
 {
     DList!Node children;
 }
Then use DList? DList is not SList, they were written by different people. -Steve
SList.Range has moveFront, DList.Range does not. If I comment out SList.Range.moveFront, it compiles with SList.
Jan 15 2015
parent reply zeljkog <zeljkog home.com> writes:
On 16.01.15 08:04, zeljkog wrote:
 On 15.01.15 23:30, Steven Schveighoffer wrote:
 On 1/15/15 9:56 AM, zeljkog wrote:
 This compiles:

 import std.container;

 class Node
 {
     DList!Node children;
 }
Then use DList? DList is not SList, they were written by different people. -Steve
SList.Range has moveFront, DList.Range does not. If I comment out SList.Range.moveFront, it compiles with SList.
And yes, looks like hasAliasing!Node (from std.algorithm.move) is only problem.
Jan 15 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/16/15 2:18 AM, zeljkog wrote:
 On 16.01.15 08:04, zeljkog wrote:
 On 15.01.15 23:30, Steven Schveighoffer wrote:
 On 1/15/15 9:56 AM, zeljkog wrote:
 This compiles:

 import std.container;

 class Node
 {
     DList!Node children;
 }
Then use DList? DList is not SList, they were written by different people. -Steve
SList.Range has moveFront, DList.Range does not. If I comment out SList.Range.moveFront, it compiles with SList.
And yes, looks like hasAliasing!Node (from std.algorithm.move) is only problem.
I think this is likely the issue. std.algorithm.move should not have to care what is inside a class to move a reference to it. I will file a bug. Thanks for digging into this. -Steve
Jan 16 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/16/15 1:24 PM, Steven Schveighoffer wrote:

 I will file a bug. Thanks for digging into this.
https://issues.dlang.org/show_bug.cgi?id=13990 https://github.com/D-Programming-Language/phobos/pull/2876 -Steve
Jan 16 2015
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
First a reminder that this sort of question is more suitable to the 
D.learn newsgroup.

On 01/13/2015 10:41 PM, qqiang wrote:

 The following code:
 ```D
 template PowerHeap(T) {
      import std.container : SList;

      private alias PowerForest = SList!PowerNode;

      private final class PowerNode {
          ...
      }

      final class PowerHead {
          ...
      }
 }

 unittest {
      PowerHeap!int h;
 }
 ```
I started with your code and produced the following one: template PowerHeap(T) { import std.container : SList; private alias PowerForest = SList!PowerNode; private final class PowerNode { // ... } final class PowerHead { // ... } } unittest { PowerHeap!int h; // <-- Compilation error here } void main() {}
 failed to compile and get the error: PowerHeap!int.PowerNode: no size
 yet for forward reference.
What compiler and version are you using? I received a different error with the git head dmd: Error: PowerHeap!int is used as a type The compiler is right, PowerHeap!int is a template instantiation that wraps a number of definitions. Did you mean one of those? The following compiles: unittest { PowerHeap!int.PowerHead h; // <-- now compiles }
 I've googled and found no straightforward solution to this issue. The
 how can I modify my code to eliminate this error?
Please provide exact code so that... Oh, wait! I've just noticed that your error message has PowerHeap!int.PowerNode in it. Let me try with that: unittest { PowerHeap!int.PowerNode h; // <-- this compiles as well } Yeah, please provide exact code. :) Ali
Jan 14 2015
parent "qqiang" <wqzhiep gmail.com> writes:
On Wednesday, 14 January 2015 at 08:31:13 UTC, Ali Çehreli wrote:
 First a reminder that this sort of question is more suitable to 
 the D.learn newsgroup.

 On 01/13/2015 10:41 PM, qqiang wrote:

 The following code:
 ```D
 template PowerHeap(T) {
      import std.container : SList;

      private alias PowerForest = SList!PowerNode;

      private final class PowerNode {
          ...
      }

      final class PowerHead {
          ...
      }
 }

 unittest {
      PowerHeap!int h;
 }
 ```
I started with your code and produced the following one: template PowerHeap(T) { import std.container : SList; private alias PowerForest = SList!PowerNode; private final class PowerNode { // ... } final class PowerHead { // ... } } unittest { PowerHeap!int h; // <-- Compilation error here } void main() {}
 failed to compile and get the error: PowerHeap!int.PowerNode:
no size
 yet for forward reference.
What compiler and version are you using? I received a different error with the git head dmd: Error: PowerHeap!int is used as a type The compiler is right, PowerHeap!int is a template instantiation that wraps a number of definitions. Did you mean one of those? The following compiles: unittest { PowerHeap!int.PowerHead h; // <-- now compiles }
 I've googled and found no straightforward solution to this
issue. The
 how can I modify my code to eliminate this error?
Please provide exact code so that... Oh, wait! I've just noticed that your error message has PowerHeap!int.PowerNode in it. Let me try with that: unittest { PowerHeap!int.PowerNode h; // <-- this compiles as well } Yeah, please provide exact code. :) Ali
Thanks for your reminder. I'm sorry that I've provided wrong code. This is the exact code: ------------------------------------------------------------------- template PowerHeap(T) { import std.container : SList; private alias PowerForest = SList!PowerNode; private final class PowerNode { private { T payload_; uint rank_; PowerForest children_; } } final class PowerHeap { private { PowerNode top_; PowerForest forest_; uint size_; } } } unittest { PowerHeap!int h; } ---------------------------------------------------------------------- My compiler is v2.066.1
Jan 14 2015