www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Accessing a field of a containing class from within a nested class

reply Charles Hixson via Digitalmars-d-learn writes:
The class Node is contained within the struct BTree.
The field   btFile is contained within the struct BTree.
The statement is within a function within the Node class.

I've tried many variations, here are a few:

btFile.write(self.nodeId, cast(void*)&(self));
results in:
need 'this' for 'btFile' of type 'BlockFile'

this.btFile.write(self.nodeId, cast(void*)&(self));
results in:
Error: no property 'btFile' for type 'btplus.BTree.Node'

this.BTree.btFile.write(self.nodeId, cast(void*)&(self));
results in:
  Error: constructor btplus.BTree.this (string fName) is not callable 
using argument types (Node)

Perhaps BTree needs to be a class?  I made it a struct because I want it 
to definitely close properly when it
goes out of scope.
Apr 01 2015
next sibling parent reply "anonymous" <anonymous example.com> writes:
On Wednesday, 1 April 2015 at 18:26:49 UTC, Charles Hixson wrote:
 Perhaps BTree needs to be a class?
yes
Apr 01 2015
parent Charles Hixson via Digitalmars-d-learn writes:
On 04/01/2015 11:39 AM, anonymous via Digitalmars-d-learn wrote:
 On Wednesday, 1 April 2015 at 18:26:49 UTC, Charles Hixson wrote:
 Perhaps BTree needs to be a class?
yes
Thanks. Sigh. I was hoping to preserve the determinate closing that one gets with a struct.
Apr 01 2015
prev sibling next sibling parent "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 1 April 2015 at 18:26:49 UTC, Charles Hixson wrote:
 Perhaps BTree needs to be a class?  I made it a struct because 
 I want it to definitely close properly when it
 goes out of scope.
Maybe `scoped` can help:
Apr 01 2015
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 04/01/2015 11:25 AM, Charles Hixson via Digitalmars-d-learn wrote:> 
The class Node is contained within the struct BTree.
 The field   btFile is contained within the struct BTree.
 The statement is within a function within the Node class.

 I've tried many variations, here are a few:

 btFile.write(self.nodeId, cast(void*)&(self));
 results in:
 need 'this' for 'btFile' of type 'BlockFile'

 this.btFile.write(self.nodeId, cast(void*)&(self));
 results in:
 Error: no property 'btFile' for type 'btplus.BTree.Node'

 this.BTree.btFile.write(self.nodeId, cast(void*)&(self));
 results in:
   Error: constructor btplus.BTree.this (string fName) is not callable
 using argument types (Node)

 Perhaps BTree needs to be a class?  I made it a struct because I want it
 to definitely close properly when it
 goes out of scope.
Can you modify the definition of Node? If so, perhaps it's possible construct Node objects with a reference to its btFile: import std.stdio; class Node { int *btFile; this(int *btFile) { this.btFile = btFile; } void foo() { writeln(*btFile); } } struct BTree { int btFile; Node node; this(int btFile) { this.btFile = btFile; this.node = new Node(&this.btFile); } } void main() { auto bt = BTree(42); bt.node.foo(); } Ali
Apr 01 2015
parent Charles Hixson via Digitalmars-d-learn writes:
Yess.....but there are LOTS of nodes/BTree, and each node would need to 
check whether the btFile was already initialized, et (ugh!) cetera.  So 
while possible, that's an even worse answer than depending on people 
closing the BTree properly.  I *am* going to separate the close routine 
from the destructor, so that it can be closed manually, and if not the 
destructor is going to print a warning message if the file is still open 
when it's called, but this isn't the best design.  This design calls for 
users of what is essentially a library routine to remember to properly 
close it...or to hope that the destructor gets called before the program 
quits.

In a practical sense, since I'm probably going to be the only user of 
the code, making BTree a class should be ok, but it feels like a bad 
design decision.  I don't want to make the file a static member of the 
Node class (which would answer some of the problems) because that would 
prevent there being more than one BTree open at a time, and I expect to 
need at least two of them, and possibly more.  Were I to do that I might 
as well make it a file level variable.

So the ways to handle lack of a determinate close to the file are all 
clumsy, and a bit error prone.  But I think having a file handle in each 
Node would be MUCH worse.  How could you *ever* know when to close it, 
as Nodes are being opened and freed all the time.  And most of the time 
many are open at once.  Additionally, all the Nodes being closed doesn't 
mean the BTree is closed (though that's the most likely reason) so you 
can't even use a global counter.

OTOH, this is still in the design stage, so if a good answer were to be 
available, now would be the best time to put it in.  (FWIW both the Key 
and the Data will be required to pass !hasIndirections!(T). I'm not 
planning a truly general BTree.  In my test version the Key is a ulong 
and the Data is a struct containing only ulongs and ints.)

On 04/01/2015 03:03 PM, Ali Çehreli via Digitalmars-d-learn wrote:
 On 04/01/2015 11:25 AM, Charles Hixson via Digitalmars-d-learn wrote:> 
 The class Node is contained within the struct BTree.
 The field   btFile is contained within the struct BTree.
 The statement is within a function within the Node class.

 I've tried many variations, here are a few:

 btFile.write(self.nodeId, cast(void*)&(self));
 results in:
 need 'this' for 'btFile' of type 'BlockFile'

 this.btFile.write(self.nodeId, cast(void*)&(self));
 results in:
 Error: no property 'btFile' for type 'btplus.BTree.Node'

 this.BTree.btFile.write(self.nodeId, cast(void*)&(self));
 results in:
   Error: constructor btplus.BTree.this (string fName) is not callable
 using argument types (Node)

 Perhaps BTree needs to be a class?  I made it a struct because I 
want it
 to definitely close properly when it
 goes out of scope.
Can you modify the definition of Node? If so, perhaps it's possible construct Node objects with a reference to its btFile: import std.stdio; class Node { int *btFile; this(int *btFile) { this.btFile = btFile; } void foo() { writeln(*btFile); } } struct BTree { int btFile; Node node; this(int btFile) { this.btFile = btFile; this.node = new Node(&this.btFile); } } void main() { auto bt = BTree(42); bt.node.foo(); } Ali
Apr 01 2015