digitalmars.D - inner member classes in final outer class
- coxalan <coxalan web.de> Sep 15 2007
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> Sep 15 2007
- coxalan <coxalan web.de> Sep 15 2007
- Kirk McDonald <kirklin.mcdonald gmail.com> Sep 15 2007
- Regan Heath <regan netmail.co.nz> Sep 16 2007
- Bruno Medeiros <brunodomedeiros+spam com.gmail> Sep 16 2007
- Regan Heath <regan netmail.co.nz> Sep 16 2007
- Bruno Medeiros <brunodomedeiros+spam com.gmail> Sep 16 2007
- Regan Heath <regan netmail.co.nz> Sep 16 2007
- Bruno Medeiros <brunodomedeiros+spam com.gmail> Sep 17 2007
- Regan Heath <regan netmail.co.nz> Sep 17 2007
- Bruno Medeiros <brunodomedeiros+spam com.gmail> Sep 17 2007
- Regan Heath <regan netmail.co.nz> Sep 17 2007
- Bruno Medeiros <brunodomedeiros+spam com.gmail> Sep 17 2007
- Regan Heath <regan netmail.co.nz> Sep 17 2007
- Bruno Medeiros <brunodomedeiros+spam com.gmail> Sep 18 2007
- coxalan <coxalan web.de> Sep 20 2007
- Bruno Medeiros <brunodomedeiros+spam com.gmail> Sep 16 2007
Hello,
Consider this code:
class Outer {
class Inner {
}
}
void main() {
final Outer o = new Outer;
o.Inner i1 = o.new Inner;
o.Inner i2 = o.new Inner;
o.Inner i3 = o.new Inner;
}
According to http://www.digitalmars.com/d/class.html, each "o.Inner" instance
contains a "context pointer" to the enclosing outer class.
But in this case the enclosing outer class "o" is final, so in my opinion there
is no need to store the context pointer in i1, i2 and i3 again and again.
Instead, always the address stored in the reference "o" could be used.
Now two questions:
1) Would it be possible to have an optimization in the D compiler which removes
the context pointer in the case of final outer classes? Or will that result in
other problems I currently do not realize?
2) With the current dmd compiler, is there a way (maybe using template magic)
for a similar object design which circumvents the context pointer?
A suggestion was made here:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=58154
But the problem with that code is that I cannot have more than one outer class
of the same type possessing inner classes.
Thanks,
coxalan
Sep 15 2007
coxalan wrote:Consider this code: class Outer { class Inner { } } void main() { final Outer o = new Outer; o.Inner i1 = o.new Inner; o.Inner i2 = o.new Inner; o.Inner i3 = o.new Inner; } According to http://www.digitalmars.com/d/class.html, each "o.Inner" instance contains a "context pointer" to the enclosing outer class. But in this case the enclosing outer class "o" is final, so in my opinion there is no need to store the context pointer in i1, i2 and i3 again and again. Instead, always the address stored in the reference "o" could be used.
I'm pretty sure the context pointer is already a copy of 'o' (not a pointer to it as you seem to think). I just looked it up; from the documentation (the page you linked above): ===== Non-static nested classes work by containing an extra hidden member (called the context pointer) that is the frame pointer of the enclosing function if it is nested inside a function, or the this of the enclosing class's instance if it is nested inside a class. ===== In the code above the class is nested in another class (not a function), so the context pointer is the 'this' of the enclosing class, i.e. a copy of 'o'.
Sep 15 2007
Frits van Bommel Wrote:I just looked it up; from the documentation (the page you linked above): ===== Non-static nested classes work by containing an extra hidden member (called the context pointer) that is the frame pointer of the enclosing function if it is nested inside a function, or the this of the enclosing class's instance if it is nested inside a class. ===== In the code above the class is nested in another class (not a function), so the context pointer is the 'this' of the enclosing class, i.e. a copy of 'o'.
Yes, the "this" of the outer class is stored in each inner member class. So on a 32 bit machine: Each inner class contains 4 extra bytes storing the address of the outer class (This is what I meant by using the term "pointer": An address is stored.) In my code example, the outer class 'o' is final. That means that the reference stored in 'o' will never change, so for all instances of 'o.Inner' the address stored in the context pointer will be the same. This is redundant, and I wonder if the optimization could be done to _not_ store the reference pointers for instances of member classes of final outer classes.
Sep 15 2007
coxalan wrote:Frits van Bommel Wrote:I just looked it up; from the documentation (the page you linked above): ===== Non-static nested classes work by containing an extra hidden member (called the context pointer) that is the frame pointer of the enclosing function if it is nested inside a function, or the this of the enclosing class's instance if it is nested inside a class. ===== In the code above the class is nested in another class (not a function), so the context pointer is the 'this' of the enclosing class, i.e. a copy of 'o'.
Yes, the "this" of the outer class is stored in each inner member class. So on a 32 bit machine: Each inner class contains 4 extra bytes storing the address of the outer class (This is what I meant by using the term "pointer": An address is stored.) In my code example, the outer class 'o' is final. That means that the reference stored in 'o' will never change, so for all instances of 'o.Inner' the address stored in the context pointer will be the same. This is redundant, and I wonder if the optimization could be done to _not_ store the reference pointers for instances of member classes of final outer classes.
That o is final is irrelevant. Consider: Outer.Inner foo() { final Outer o = new Outer; return o.new Inner; } The lifetime of the instance of the Inner class can easily exceed that of the original reference to the instance of the Outer class which created it. Therefore, the Inner class must have its own reference to the Outer class. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Sep 15 2007
Kirk McDonald wrote:coxalan wrote:Frits van Bommel Wrote:I just looked it up; from the documentation (the page you linked above): ===== Non-static nested classes work by containing an extra hidden member (called the context pointer) that is the frame pointer of the enclosing function if it is nested inside a function, or the this of the enclosing class's instance if it is nested inside a class. ===== In the code above the class is nested in another class (not a function), so the context pointer is the 'this' of the enclosing class, i.e. a copy of 'o'.
Yes, the "this" of the outer class is stored in each inner member class. So on a 32 bit machine: Each inner class contains 4 extra bytes storing the address of the outer class (This is what I meant by using the term "pointer": An address is stored.) In my code example, the outer class 'o' is final. That means that the reference stored in 'o' will never change, so for all instances of 'o.Inner' the address stored in the context pointer will be the same. This is redundant, and I wonder if the optimization could be done to _not_ store the reference pointers for instances of member classes of final outer classes.
That o is final is irrelevant. Consider: Outer.Inner foo() { final Outer o = new Outer; return o.new Inner; } The lifetime of the instance of the Inner class can easily exceed that of the original reference to the instance of the Outer class which created it. Therefore, the Inner class must have its own reference to the Outer class.
Must it? What if the inner classes had a static reference to the outer? eg. class Outer { class Inner { static Outer outer; //only one copy for all instances of Inner } } So, if you have X instances of Outer, creating Y instances of Inner you will have only X outer references, instead of X*Y outer references. The static reference will prevent the destruction of the outer when it leaves scope in your example above, but when will it be destroyed? How does D currently deal with this in a normal "class contains static reference" situation? Are these objects destroyed only at program exit? I'm not sure I understand how static references or even normal members are implemented, are they implemented in the same was as global variables? Should static outer references be the default behaviour? It seems to be a neat little optimisation, assuming it doesn't cause destruction problems as described above and maybe even then. The only case I can imagine wanting a seperate outer reference for each inner class is when I need to move inner classes from one outer to another, eg auto o = new Outer; auto p = new Outer; auto i = new o.Inner; i.outer = p; I'm not sure this is even possible currently and I can't think of a reason why you might want to do this. Regan
Sep 16 2007
Regan Heath wrote:Kirk McDonald wrote:coxalan wrote:Frits van Bommel Wrote:I just looked it up; from the documentation (the page you linked above): ===== Non-static nested classes work by containing an extra hidden member (called the context pointer) that is the frame pointer of the enclosing function if it is nested inside a function, or the this of the enclosing class's instance if it is nested inside a class. ===== In the code above the class is nested in another class (not a function), so the context pointer is the 'this' of the enclosing class, i.e. a copy of 'o'.
Yes, the "this" of the outer class is stored in each inner member class. So on a 32 bit machine: Each inner class contains 4 extra bytes storing the address of the outer class (This is what I meant by using the term "pointer": An address is stored.) In my code example, the outer class 'o' is final. That means that the reference stored in 'o' will never change, so for all instances of 'o.Inner' the address stored in the context pointer will be the same. This is redundant, and I wonder if the optimization could be done to _not_ store the reference pointers for instances of member classes of final outer classes.
That o is final is irrelevant. Consider: Outer.Inner foo() { final Outer o = new Outer; return o.new Inner; } The lifetime of the instance of the Inner class can easily exceed that of the original reference to the instance of the Outer class which created it. Therefore, the Inner class must have its own reference to the Outer class.
Must it? What if the inner classes had a static reference to the outer? eg. class Outer { class Inner { static Outer outer; //only one copy for all instances of Inner } } So, if you have X instances of Outer, creating Y instances of Inner you will have only X outer references, instead of X*Y outer references.
That's wrong. You don't have X outer references, there is only one instance of outer (aka Outer.Inner.outer). A static attribute in a member declaration makes it unique, even if the member is an inner class. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 16 2007
Bruno Medeiros wrote:Regan Heath wrote:Kirk McDonald wrote:coxalan wrote:Frits van Bommel Wrote:I just looked it up; from the documentation (the page you linked above): ===== Non-static nested classes work by containing an extra hidden member (called the context pointer) that is the frame pointer of the enclosing function if it is nested inside a function, or the this of the enclosing class's instance if it is nested inside a class. ===== In the code above the class is nested in another class (not a function), so the context pointer is the 'this' of the enclosing class, i.e. a copy of 'o'.
Yes, the "this" of the outer class is stored in each inner member class. So on a 32 bit machine: Each inner class contains 4 extra bytes storing the address of the outer class (This is what I meant by using the term "pointer": An address is stored.) In my code example, the outer class 'o' is final. That means that the reference stored in 'o' will never change, so for all instances of 'o.Inner' the address stored in the context pointer will be the same. This is redundant, and I wonder if the optimization could be done to _not_ store the reference pointers for instances of member classes of final outer classes.
That o is final is irrelevant. Consider: Outer.Inner foo() { final Outer o = new Outer; return o.new Inner; } The lifetime of the instance of the Inner class can easily exceed that of the original reference to the instance of the Outer class which created it. Therefore, the Inner class must have its own reference to the Outer class.
Must it? What if the inner classes had a static reference to the outer? eg. class Outer { class Inner { static Outer outer; //only one copy for all instances of Inner } } So, if you have X instances of Outer, creating Y instances of Inner you will have only X outer references, instead of X*Y outer references.
That's wrong. You don't have X outer references, there is only one instance of outer (aka Outer.Inner.outer). A static attribute in a member declaration makes it unique, even if the member is an inner class.
One of us is missunderstanding something :) I was describing this case: class Outer { class Inner { } } where Inner automagically has an 'outer' member which refers to the Outer class instance. Described here: http://www.digitalmars.com/d/class.html "Non-static nested classes work by containing an extra hidden member (called the context pointer) that is the frame pointer of the enclosing function if it is nested inside a function, or the this of the enclosing class's instance if it is nested inside a class." (NOTE: I'm not referring to the class definition I gave above which was a fictional representation of how D _could_ implement the context pointer as a static reference) Then when I said "So, if you have X instances of Outer, creating Y instances of Inner" I meant _if_ you code something like this: const int X = 10; const int Y = 10; for(int i = 0; i < X; i++) { auto o = new Outer; for(int j = 0; j < Y; j++) { auto i = new o.Inner; } } You will have X (10) outer objects each with Y (10) inner objects, each containing a context pointer to the outer object, therefore you have X*Y (100) context pointers. Making the context reference static would decrease this number to X (10) context pointers. Make sense, or am I missunderstanding something? Regan
Sep 16 2007
Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Kirk McDonald wrote:coxalan wrote:Frits van Bommel Wrote:I just looked it up; from the documentation (the page you linked above): ===== Non-static nested classes work by containing an extra hidden member (called the context pointer) that is the frame pointer of the enclosing function if it is nested inside a function, or the this of the enclosing class's instance if it is nested inside a class. ===== In the code above the class is nested in another class (not a function), so the context pointer is the 'this' of the enclosing class, i.e. a copy of 'o'.
Yes, the "this" of the outer class is stored in each inner member class. So on a 32 bit machine: Each inner class contains 4 extra bytes storing the address of the outer class (This is what I meant by using the term "pointer": An address is stored.) In my code example, the outer class 'o' is final. That means that the reference stored in 'o' will never change, so for all instances of 'o.Inner' the address stored in the context pointer will be the same. This is redundant, and I wonder if the optimization could be done to _not_ store the reference pointers for instances of member classes of final outer classes.
That o is final is irrelevant. Consider: Outer.Inner foo() { final Outer o = new Outer; return o.new Inner; } The lifetime of the instance of the Inner class can easily exceed that of the original reference to the instance of the Outer class which created it. Therefore, the Inner class must have its own reference to the Outer class.
Must it? What if the inner classes had a static reference to the outer? eg. class Outer { class Inner { static Outer outer; //only one copy for all instances of Inner } } So, if you have X instances of Outer, creating Y instances of Inner you will have only X outer references, instead of X*Y outer references.
That's wrong. You don't have X outer references, there is only one instance of outer (aka Outer.Inner.outer). A static attribute in a member declaration makes it unique, even if the member is an inner class.
One of us is missunderstanding something :) I was describing this case: class Outer { class Inner { } }
Describing that case where? Your most recent post was this:Must it? What if the inner classes had a static reference to the
eg. class Outer { class Inner { static Outer outer; //only one copy for all instances of Inner } } So, if you have X instances of Outer, creating Y instances of Inner you will have only X outer references, instead of X*Y outer references.
Which I interpret as describing this case: class Outer { class Inner { static Outer outer; //only one copy for all instances of Inner } } ... which is the one I was commenting on my reply ... :/ ? -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 16 2007
Bruno Medeiros wrote:Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Kirk McDonald wrote:coxalan wrote:Frits van Bommel Wrote:I just looked it up; from the documentation (the page you linked above): ===== Non-static nested classes work by containing an extra hidden member (called the context pointer) that is the frame pointer of the enclosing function if it is nested inside a function, or the this of the enclosing class's instance if it is nested inside a class. ===== In the code above the class is nested in another class (not a function), so the context pointer is the 'this' of the enclosing class, i.e. a copy of 'o'.
Yes, the "this" of the outer class is stored in each inner member class. So on a 32 bit machine: Each inner class contains 4 extra bytes storing the address of the outer class (This is what I meant by using the term "pointer": An address is stored.) In my code example, the outer class 'o' is final. That means that the reference stored in 'o' will never change, so for all instances of 'o.Inner' the address stored in the context pointer will be the same. This is redundant, and I wonder if the optimization could be done to _not_ store the reference pointers for instances of member classes of final outer classes.
That o is final is irrelevant. Consider: Outer.Inner foo() { final Outer o = new Outer; return o.new Inner; } The lifetime of the instance of the Inner class can easily exceed that of the original reference to the instance of the Outer class which created it. Therefore, the Inner class must have its own reference to the Outer class.
Must it? What if the inner classes had a static reference to the outer? eg. class Outer { class Inner { static Outer outer; //only one copy for all instances of Inner } } So, if you have X instances of Outer, creating Y instances of Inner you will have only X outer references, instead of X*Y outer references.
That's wrong. You don't have X outer references, there is only one instance of outer (aka Outer.Inner.outer). A static attribute in a member declaration makes it unique, even if the member is an inner class.
One of us is missunderstanding something :) I was describing this case: class Outer { class Inner { } }
Describing that case where? Your most recent post was this:
I was describing the OP's problem case, granted I did so following my example solution case which was perhaps confusing.>>> Must it? What if the inner classes had a static reference to the outer? >>> eg. >>> >>> class Outer >>> { >>> class Inner >>> { >>> static Outer outer; //only one copy for all instances of Inner >>> } >>> } >>> >>> So, if you have X instances of Outer, creating Y instances of Inner >>> you will have only X outer references, instead of X*Y outer references. Which I interpret as describing this case: class Outer { class Inner { static Outer outer; //only one copy for all instances of Inner } } .... which is the one I was commenting on my reply ... :/ ?
Well, that's where you're confused (by my badly constructed post). I was describing the OP's problem case, the current D behaviour (unless I'm mistaken) which is for every instance of the inner class to have a context pointer. The example above using static was my suggested solution, of sorts. Regan
Sep 16 2007
Regan Heath wrote:Well, that's where you're confused (by my badly constructed post). I was describing the OP's problem case, the current D behaviour (unless I'm mistaken) which is for every instance of the inner class to have a context pointer. The example above using static was my suggested solution, of sorts. Regan
Ok, I know you were talking first about current D behavior, but I was talking about your suggested solution. You do understand why that solution wouldn't work as you expected? -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 17 2007
Bruno Medeiros wrote:Regan Heath wrote:Well, that's where you're confused (by my badly constructed post). I was describing the OP's problem case, the current D behaviour (unless I'm mistaken) which is for every instance of the inner class to have a context pointer. The example above using static was my suggested solution, of sorts. Regan
Ok, I know you were talking first about current D behavior, but I was talking about your suggested solution. You do understand why that solution wouldn't work as you expected?
Nope. Are you referring to your comment: "Removing the context pointer would imply having different, incompatible versions of the Inner class, and since that alters program semantics the compiler cannot do that" ? Regan
Sep 17 2007
Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Well, that's where you're confused (by my badly constructed post). I was describing the OP's problem case, the current D behaviour (unless I'm mistaken) which is for every instance of the inner class to have a context pointer. The example above using static was my suggested solution, of sorts. Regan
Ok, I know you were talking first about current D behavior, but I was talking about your suggested solution. You do understand why that solution wouldn't work as you expected?
Nope. Are you referring to your comment: "Removing the context pointer would imply having different, incompatible versions of the Inner class, and since that alters program semantics the compiler cannot do that" ? Regan
No, I mean making the context pointer static. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 17 2007
Bruno Medeiros wrote:Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Well, that's where you're confused (by my badly constructed post). I was describing the OP's problem case, the current D behaviour (unless I'm mistaken) which is for every instance of the inner class to have a context pointer. The example above using static was my suggested solution, of sorts. Regan
Ok, I know you were talking first about current D behavior, but I was talking about your suggested solution. You do understand why that solution wouldn't work as you expected?
Nope. Are you referring to your comment: "Removing the context pointer would imply having different, incompatible versions of the Inner class, and since that alters program semantics the compiler cannot do that" ? Regan
No, I mean making the context pointer static.
Please explain why it wont work (as I expect - assuming you're not confused about what I expect too <g>)? Regan
Sep 17 2007
Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Well, that's where you're confused (by my badly constructed post). I was describing the OP's problem case, the current D behaviour (unless I'm mistaken) which is for every instance of the inner class to have a context pointer. The example above using static was my suggested solution, of sorts. Regan
Ok, I know you were talking first about current D behavior, but I was talking about your suggested solution. You do understand why that solution wouldn't work as you expected?
Nope. Are you referring to your comment: "Removing the context pointer would imply having different, incompatible versions of the Inner class, and since that alters program semantics the compiler cannot do that" ? Regan
No, I mean making the context pointer static.
Please explain why it wont work (as I expect - assuming you're not confused about what I expect too <g>)? Regan
Damn it, I already did! :P You said you wanted to "have only X outer references, instead of X*Y outer references", right? And like I said, if you (or the compiler) made the context pointer static (as in 'static' storage class in a var declaration), you would have only 1 outer reference (not X), since static would make that "variable" unique. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 17 2007
Bruno Medeiros wrote:Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Well, that's where you're confused (by my badly constructed post). I was describing the OP's problem case, the current D behaviour (unless I'm mistaken) which is for every instance of the inner class to have a context pointer. The example above using static was my suggested solution, of sorts. Regan
Ok, I know you were talking first about current D behavior, but I was talking about your suggested solution. You do understand why that solution wouldn't work as you expected?
Nope. Are you referring to your comment: "Removing the context pointer would imply having different, incompatible versions of the Inner class, and since that alters program semantics the compiler cannot do that" ? Regan
No, I mean making the context pointer static.
Please explain why it wont work (as I expect - assuming you're not confused about what I expect too <g>)? Regan
Damn it, I already did! :P You said you wanted to "have only X outer references, instead of X*Y outer references", right? And like I said, if you (or the compiler) made the context pointer static (as in 'static' storage class in a var declaration), you would have only 1 outer reference (not X), since static would make that "variable" unique.
Doh! Somehow I totally missed that, you're quite correct. :) Regan
Sep 17 2007
Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Bruno Medeiros wrote:Regan Heath wrote:Well, that's where you're confused (by my badly constructed post). I was describing the OP's problem case, the current D behaviour (unless I'm mistaken) which is for every instance of the inner class to have a context pointer. The example above using static was my suggested solution, of sorts. Regan
Ok, I know you were talking first about current D behavior, but I was talking about your suggested solution. You do understand why that solution wouldn't work as you expected?
Nope. Are you referring to your comment: "Removing the context pointer would imply having different, incompatible versions of the Inner class, and since that alters program semantics the compiler cannot do that" ? Regan
No, I mean making the context pointer static.
Please explain why it wont work (as I expect - assuming you're not confused about what I expect too <g>)? Regan
Damn it, I already did! :P You said you wanted to "have only X outer references, instead of X*Y outer references", right? And like I said, if you (or the compiler) made the context pointer static (as in 'static' storage class in a var declaration), you would have only 1 outer reference (not X), since static would make that "variable" unique.
Doh! Somehow I totally missed that, you're quite correct. :) Regan
Finally! :) -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 18 2007
Hello, thanks for all the answers on this topic. Now I understand that with the current implementation of inner member classes, it is _not_ possible to drop the context pointer for final outer classes. Regan Heath Wrote:Should static outer references be the default behaviour? It seems to be a neat little optimisation, assuming it doesn't cause destruction problems as described above and maybe even then. The only case I can imagine wanting a seperate outer reference for each inner class is when I need to move inner classes from one outer to another, eg auto o = new Outer; auto p = new Outer; auto i = new o.Inner; i.outer = p; I'm not sure this is even possible currently and I can't think of a reason why you might want to do this. Regan
This is quite similar to my feelings about member classes: Consider again: class Outer { class Inner { } } main() { Outer o = new Outer; o.Inner i = o.new Inner; Outer o2 = new Outer; o2.Inner i2 = o2.new Inner; } In my dream world the preferable behaviour of inner member classes would be like this: Then the type of 'i' should be 'o.Inner'. That would imply that the reference pointer to 'o' is part of the type, and thus there is no need to store is. Furthermore, 'o.Inner' and 'o2.Inner' would be different types and thus, they could have different static class members. But the real behaviour is this: Although I write 'o.Inner' above, I could have written 'Outer.Inner' as well, and really the type of 'i' is 'Outer.Inner' and not 'o.Inner'. That means that the context pointer cannot be dropped (because for example I could do i2=i), and that 'o.Inner' and 'o2.Inner' have the same static namespace. Like Regan i wonder if there are cases where the 2nd behaviour is the better one, and if yes, what such a case looks like. I know that the first variant which I would like to see raises some issues: * 'o' probably should be final. * The problem addressed by Kirk McDonald: 'o.Inner' objects could have a longer lifetime than the outer Object 'o'. This could be solved in two ways: Firstly, the garbage collector does not delete 'o' as long as 'o.Inner' objects exist. Secondly, allow 'o.Inner' objects only within the scope of 'o'. * The main problem: The symbol 'o' only exists within its scope. So the type 'o.Inner' only exists within the scope of 'o'. coxalan
Sep 20 2007
coxalan wrote:Hello, Consider this code: class Outer { class Inner { } } void main() { final Outer o = new Outer; o.Inner i1 = o.new Inner; o.Inner i2 = o.new Inner; o.Inner i3 = o.new Inner; } According to http://www.digitalmars.com/d/class.html, each "o.Inner" instance contains a "context pointer" to the enclosing outer class. But in this case the enclosing outer class "o" is final, so in my opinion there is no need to store the context pointer in i1, i2 and i3 again and again. Instead, always the address stored in the reference "o" could be used. Now two questions: 1) Would it be possible to have an optimization in the D compiler which removes the context pointer in the case of final outer classes? Or will that result in other problems I currently do not realize?
No. Removing the context pointer would imply having different, incompatible versions of the Inner class, and since that alters program semantics the compiler cannot do that. (unless it was an incredibly smart compiler capable of performing whole program optimizations, something which at this point is like sci-fi :P). You'd have to explicitly state that in the program. (see below)2) With the current dmd compiler, is there a way (maybe using template magic) for a similar object design which circumvents the context pointer? A suggestion was made here: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=58154 But the problem with that code is that I cannot have more than one outer class of the same type possessing inner classes. Thanks, coxalan
I was thinking the following: class Outer { } class Inner(alias outer) { static assert(is(outer : Outer)); // Just a check } final Outer o1 = new Outer(); final Outer o2 = new Outer(); void main() { Inner i1 = new Inner!(o1); Inner i2 = new Inner!(o1); Inner i3 = new Inner!(o2); Inner i4 = new Inner!(o2); } Having each Inner class parameterized with an alias, is like having a compile-time constant member (the outer variable). This poses some restrictions though: the outer classes variables cannot be declared inside functions (because variables inside functions cannot be used as alias parameters), and the Inner classes are no longer compatible (covariant) with each other, although you can create a common Inner superclass. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 16 2007









Bruno Medeiros <brunodomedeiros+spam com.gmail> 