www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Forward references and more

reply bearophile <bearophileHUGS lycos.com> writes:
What's wrong with this code?

struct MemoryPool(T) {
    alias T[100_000 / T.sizeof] Chunk;
    Chunk*[] chunks;
}
struct Foo {
    int x;
    MemoryPool!(Foo) pool;
}
void main() {}

It prints "Error: struct problem.Foo no size yet for forward reference".
T.sizeof must be 8 in all cases.


So I have tried to pull pool out:

struct MemoryPool(T) {
    alias T[100_000 / T.sizeof] Chunk;
    Chunk*[] chunks;
}
MemoryPool!(Foo) pool;
struct Foo {
    int x;
    // here uses pool
}
void main() {}

But there's a problem still:
Error: struct problem2.Foo no size yet for forward reference

To compile the code I have to move pool forward still:

struct MemoryPool(T) {
    alias T[100_000 / T.sizeof] Chunk;
    Chunk*[] chunks;
}
struct Foo {
    int x;
    // here uses pool
}
MemoryPool!(Foo) pool;
void main() {}

When possible it's better to avoid global variables. To avoid the global
variable I may pass the instance pool to Foo. But to do this Foo has to become
a struct template. But I am not sure how I can do this.
Do you have any comments or suggestions?

Bye and thank you,
bearophile
Oct 12 2009
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
 T.sizeof must be 8 in all cases.
Ignore this line, please :-)
Oct 12 2009
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 12 Oct 2009 05:26:58 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:

 What's wrong with this code?

 struct MemoryPool(T) {
     alias T[100_000 / T.sizeof] Chunk;
     Chunk*[] chunks;
 }
 struct Foo {
     int x;
     MemoryPool!(Foo) pool;
 }
 void main() {}

 It prints "Error: struct problem.Foo no size yet for forward reference".
 T.sizeof must be 8 in all cases.


 So I have tried to pull pool out:

 struct MemoryPool(T) {
     alias T[100_000 / T.sizeof] Chunk;
     Chunk*[] chunks;
 }
 MemoryPool!(Foo) pool;
 struct Foo {
     int x;
     // here uses pool
 }
 void main() {}

 But there's a problem still:
 Error: struct problem2.Foo no size yet for forward reference

 To compile the code I have to move pool forward still:

 struct MemoryPool(T) {
     alias T[100_000 / T.sizeof] Chunk;
     Chunk*[] chunks;
 }
 struct Foo {
     int x;
     // here uses pool
 }
 MemoryPool!(Foo) pool;
 void main() {}

 When possible it's better to avoid global variables. To avoid the global  
 variable I may pass the instance pool to Foo. But to do this Foo has to  
 become a struct template. But I am not sure how I can do this.
 Do you have any comments or suggestions?
It looks strange what you are doing. A Foo can have a memory pool of a lot of Foo's? Do you mean to make the memory pool static? I think that might work. I think the main problem is you are defining MemoryPool!(Foo).Chunk which specifically needs to know the size of Foo before Foo is completely declared. It's like you are doing this: struct X { X x; } Which clearly is incorrect. -Steve
Oct 12 2009
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:

 It looks strange what you are doing.  A Foo can have a memory pool of a  
 lot of Foo's?  Do you mean to make the memory pool static?
Right and yes.
I think that might work.<
It works if I use a global variable. But I'd like to not used global variables when possible.
 I think the main problem is you are defining MemoryPool!(Foo).Chunk which  
 specifically needs to know the size of Foo before Foo is completely  
 declared.
 It's like you are doing this:
 struct X
 {
    X x;
 }
 Which clearly is incorrect.
But MemoryPool.sizeof is always 8 (on a 32 bit system) because an alias takes no space. So T.sizeof must be 12. I'd like the compiler to understand this. Bye and thank you, bearophile
Oct 12 2009
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 12 Oct 2009 15:38:07 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:

 Steven Schveighoffer:

 It looks strange what you are doing.  A Foo can have a memory pool of a
 lot of Foo's?  Do you mean to make the memory pool static?
Right and yes.
 I think that might work.<
It works if I use a global variable. But I'd like to not used global variables when possible.
A static variable is essentially a scoped global variable. I think it will work if you make it static. I've used plenty of static variables that are instances of the struct they are declared in.
 I think the main problem is you are defining MemoryPool!(Foo).Chunk  
 which
 specifically needs to know the size of Foo before Foo is completely
 declared.
 It's like you are doing this:
 struct X
 {
    X x;
 }
 Which clearly is incorrect.
But MemoryPool.sizeof is always 8 (on a 32 bit system) because an alias takes no space. So T.sizeof must be 12. I'd like the compiler to understand this.
But you are also declaring the type of the chunk. I don't think it would complain if you were not trying to define a type that required the size of Foo. For example, if you did something like: struct MemoryPool(T) { T[] chunks; } I think it would work, because you aren't trying to define a type which *requires* the size of T before T is fully declared. It's sort of a chicken and egg thing. But since I think you are implementing the memory pool incorrectly (it makes no sense for each instance of an item to have a pool of itself), you should reexamine what you are trying to do. -Steve
Oct 12 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:

 A static variable is essentially a scoped global variable.  I think it  
 will work if you make it static.  I've used plenty of static variables  
 that are instances of the struct they are declared in.
It doesn't compile with static variables too, you just need few seconds to try it on Codepad: http://codepad.org/QHm2QNQ7 struct MemoryPool(T) { alias T[100_000 / T.sizeof] Chunk; static Chunk*[] chunks; } struct Foo { int x; static MemoryPool!(Foo) pool; } void main() {}
 But since I think you are implementing the memory  
 pool incorrectly (it makes no sense for each instance of an item to have a  
 pool of itself), you should reexamine what you are trying to do.
Next time I show code I'll replace all variable and type names with foo, baz, spam, etc. The memory pool in my dlibs is implemented correctly (I think). The code I've shown is just a reduced case, where I have removed the "static" too :-) Bye, bearophile
Oct 13 2009
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 13 Oct 2009 07:30:11 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:

 Steven Schveighoffer:

 A static variable is essentially a scoped global variable.  I think it
 will work if you make it static.  I've used plenty of static variables
 that are instances of the struct they are declared in.
It doesn't compile with static variables too, you just need few seconds to try it on Codepad: http://codepad.org/QHm2QNQ7 struct MemoryPool(T) { alias T[100_000 / T.sizeof] Chunk; static Chunk*[] chunks; } struct Foo { int x; static MemoryPool!(Foo) pool; } void main() {}
If that fails, then it seems like a bug to me. This works: struct Foo { static Foo var; int x; } which seems to suggest that static variables are treated like globals. You should submit a bug to get that fixed.
 But since I think you are implementing the memory
 pool incorrectly (it makes no sense for each instance of an item to  
 have a
 pool of itself), you should reexamine what you are trying to do.
Next time I show code I'll replace all variable and type names with foo, baz, spam, etc. The memory pool in my dlibs is implemented correctly (I think). The code I've shown is just a reduced case, where I have removed the "static" too :-)
It makes no sense to have a memory pool *per* instance, it makes more sense to have one pool for many instances (whether it's static or not). -Steve
Oct 13 2009
prev sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Steven Schveighoffer wrote:
 On Mon, 12 Oct 2009 05:26:58 -0400, bearophile 
 <bearophileHUGS lycos.com> wrote:
 
 What's wrong with this code?

 struct MemoryPool(T) {
     alias T[100_000 / T.sizeof] Chunk;
     Chunk*[] chunks;
 }
 struct Foo {
     int x;
     MemoryPool!(Foo) pool;
 }
 void main() {}

 It prints "Error: struct problem.Foo no size yet for forward reference".
 T.sizeof must be 8 in all cases.
The compiler does this: Instantiate MemoryPool!(Foo) But for that it needs to know Foo.sizeof. But for that it needs to know MemoryPool!(Foo).sizeof. But for that it needs to instantiate MemoryPool!(Foo) and find it's size. etc. I can see MemoryPool!(Foo) sizeof doesn't depend at all of T.sizeof because it just has a pointer. But how do you suggest to fix the compiler to understand that? What I can see is that to know MemoryPool!(Foo).sizeof the type of the alias doesn't need to be solved completely... but what would you recommend the compiler to do?
Oct 12 2009
parent bearophile <bearophileHUGS lycos.com> writes:
Ary Borenszweig:

 I can see MemoryPool!(Foo) sizeof doesn't depend at all of T.sizeof 
 because it just has a pointer.
Well, a dynamic array of pointers, but the situation is the same.
But how do you suggest to fix the compiler to understand that?<
I don't know. I don't know enough about compilers.
 What I can see is that to know MemoryPool!(Foo).sizeof the type of the 
 alias doesn't need to be solved completely... but what would you 
 recommend the compiler to do?
To see what I can see. And terminate this little dance. If that's not possible, then I'd like to have a syntax to give the necessary hint to the (less than smart) compiler. For example saying the size of one or both structs. This was just an example, but it's not the first time I fall in this problem when I create data structures in D. Bye and thank you, bearophile
Oct 12 2009