Thread overview
Accessing a field of a containing class from within a nested class
Apr 01, 2015
Charles Hixson
Apr 01, 2015
anonymous
Apr 01, 2015
Charles Hixson
Apr 01, 2015
Gary Willoughby
Apr 01, 2015
Ali Çehreli
Apr 01, 2015
Charles Hixson
April 01, 2015
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.
April 01, 2015
On Wednesday, 1 April 2015 at 18:26:49 UTC, Charles Hixson wrote:
> Perhaps BTree needs to be a class?

yes
April 01, 2015

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.
April 01, 2015
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:
http://dlang.org/phobos/std_typecons.html#.scoped
April 01, 2015
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

April 01, 2015
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
>
>