digitalmars.D - inner member classes in final outer class
- coxalan (22/22) Sep 15 2007 Hello,
- Frits van Bommel (13/30) Sep 15 2007 I'm pretty sure the context pointer is already a copy of 'o' (not a
- coxalan (5/16) Sep 15 2007 Yes, the "this" of the outer class is stored in each inner member class.
- Kirk McDonald (15/41) Sep 15 2007 That o is final is irrelevant. Consider:
- Regan Heath (31/70) Sep 16 2007 Must it? What if the inner classes had a static reference to the outer?
- Bruno Medeiros (7/62) Sep 16 2007 That's wrong. You don't have X outer references, there is only one
- Regan Heath (38/98) Sep 16 2007 One of us is missunderstanding something :)
- Bruno Medeiros (15/102) Sep 16 2007 outer?
- Regan Heath (9/114) Sep 16 2007 I was describing the OP's problem case, granted I did so following my
- Bruno Medeiros (7/17) Sep 17 2007 Ok, I know you were talking first about current D behavior, but I was
- Regan Heath (8/23) Sep 17 2007 Nope.
- Bruno Medeiros (5/32) Sep 17 2007 No, I mean making the context pointer static.
- Regan Heath (4/34) Sep 17 2007 Please explain why it wont work (as I expect - assuming you're not
- Bruno Medeiros (10/46) Sep 17 2007 Damn it, I already did! :P
- Regan Heath (3/47) Sep 17 2007 Doh! Somehow I totally missed that, you're quite correct. :)
- Bruno Medeiros (5/54) Sep 18 2007 Finally! :)
- coxalan (26/43) Sep 20 2007 Hello,
- Bruno Medeiros (31/64) Sep 16 2007 No. Removing the context pointer would imply having different,
- coxalan (8/35) Sep 16 2007 Thanks. That looks quite promising.
- Matti Niemenmaa (6/33) Sep 16 2007 Probably because he uses "Inner i[1234]" where he should use "Inner!(o[1...
- coxalan (5/37) Sep 16 2007 Thanks. Now I get:
- Matti Niemenmaa (21/57) Sep 16 2007 Alright, I took a closer look and this compiles:
- coxalan (2/65) Sep 16 2007 Thanks!
- coxalan (7/35) Sep 20 2007 One last question on this:
- Matti Niemenmaa (4/36) Sep 20 2007 Make o1 and o2 const instead of final.
- coxalan (3/41) Sep 20 2007 Thanks!
- Jarrett Billingsley (5/15) Sep 16 2007 Change those declarations of i1, i2... to something like:
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: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.orgI 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
Kirk McDonald wrote:coxalan wrote: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. ReganFrits van Bommel Wrote: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.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 16 2007
Regan Heath wrote:Kirk McDonald wrote: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#Dcoxalan wrote: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.Frits van Bommel Wrote: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.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 16 2007
Bruno Medeiros wrote:Regan Heath wrote: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? ReganKirk McDonald wrote: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.coxalan wrote: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.Frits van Bommel Wrote: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.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 16 2007
Regan Heath wrote:Bruno Medeiros wrote:Describing that case where? Your most recent post was this:Regan Heath wrote:One of us is missunderstanding something :) I was describing this case: class Outer { class Inner { } }Kirk McDonald wrote: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.coxalan wrote: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.Frits van Bommel Wrote: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.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.outer?Must it? What if the inner classes had a static reference to theWhich 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#Deg. 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.
Sep 16 2007
Bruno Medeiros wrote:Regan Heath wrote:I was describing the OP's problem case, granted I did so following my example solution case which was perhaps confusing.Bruno Medeiros wrote:Describing that case where? Your most recent post was this:Regan Heath wrote:One of us is missunderstanding something :) I was describing this case: class Outer { class Inner { } }Kirk McDonald wrote: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.coxalan wrote: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.Frits van Bommel Wrote: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.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.>>> 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. ReganOk, 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: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" ? ReganWell, 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. ReganOk, 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?
Sep 17 2007
Regan Heath wrote:Bruno Medeiros wrote:No, I mean making the context pointer static. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DRegan Heath wrote: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" ? ReganWell, 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. ReganOk, 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?
Sep 17 2007
Bruno Medeiros wrote:Regan Heath wrote:Please explain why it wont work (as I expect - assuming you're not confused about what I expect too <g>)? ReganBruno Medeiros wrote:No, I mean making the context pointer static.Regan Heath wrote: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" ? ReganWell, 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. ReganOk, 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?
Sep 17 2007
Regan Heath wrote:Bruno Medeiros wrote: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#DRegan Heath wrote:Please explain why it wont work (as I expect - assuming you're not confused about what I expect too <g>)? ReganBruno Medeiros wrote:No, I mean making the context pointer static.Regan Heath wrote: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" ? ReganWell, 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. ReganOk, 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?
Sep 17 2007
Bruno Medeiros wrote:Regan Heath wrote:Doh! Somehow I totally missed that, you're quite correct. :) ReganBruno Medeiros wrote: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.Regan Heath wrote:Please explain why it wont work (as I expect - assuming you're not confused about what I expect too <g>)? ReganBruno Medeiros wrote:No, I mean making the context pointer static.Regan Heath wrote: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" ? ReganWell, 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. ReganOk, 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?
Sep 17 2007
Regan Heath wrote:Bruno Medeiros wrote:Finally! :) -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DRegan Heath wrote:Doh! Somehow I totally missed that, you're quite correct. :) ReganBruno Medeiros wrote: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.Regan Heath wrote:Please explain why it wont work (as I expect - assuming you're not confused about what I expect too <g>)? ReganBruno Medeiros wrote:No, I mean making the context pointer static.Regan Heath wrote: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" ? ReganWell, 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. ReganOk, 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?
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. ReganThis 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, coxalanI 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 Wrote: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); }Thanks. That looks quite promising. But it does not compile for me: test.d(12): class test.Inner(alias outer) is used as a type test.d(12): variable test.main.i1 voids have no valueHaving 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),I'm do not exactly understand that. Where can I find documentation on that?and the Inner classes are no longer compatible (covariant) with each other, although you can create a common Inner superclass.That's ok. I always had the perception that o1.Inner and o2.Inner are different types. coxalan
Sep 16 2007
coxalan wrote:Bruno Medeiros Wrote:Probably because he uses "Inner i[1234]" where he should use "Inner!(o[1234]) i[1234]". The easiest solution is to use "auto" on the left-hand side of the assignments. -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) fiI 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); }Thanks. That looks quite promising. But it does not compile for me: test.d(12): class test.Inner(alias outer) is used as a type test.d(12): variable test.main.i1 voids have no value
Sep 16 2007
Matti Niemenmaa Wrote:coxalan wrote:Thanks. Now I get: test.d(5): static assert is false Disclaimer: I'm quite new to D. coxalanBruno Medeiros Wrote:Probably because he uses "Inner i[1234]" where he should use "Inner!(o[1234]) i[1234]". The easiest solution is to use "auto" on the left-hand side of the assignments.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); }Thanks. That looks quite promising. But it does not compile for me: test.d(12): class test.Inner(alias outer) is used as a type test.d(12): variable test.main.i1 voids have no value
Sep 16 2007
coxalan wrote:Matti Niemenmaa Wrote:Alright, I took a closer look and this compiles: class Outer { } class Inner(alias outer) { static assert(is(typeof(outer) : Outer)); // Just a check } final Outer o1; final Outer o2; static this() { o1 = new Outer; o2 = new Outer; } void main() { auto i1 = new Inner!(o1); auto i2 = new Inner!(o1); auto i3 = new Inner!(o2); auto i4 = new Inner!(o2); } -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) ficoxalan wrote:Thanks. Now I get: test.d(5): static assert is false Disclaimer: I'm quite new to D.Bruno Medeiros Wrote:Probably because he uses "Inner i[1234]" where he should use "Inner!(o[1234]) i[1234]". The easiest solution is to use "auto" on the left-hand side of the assignments.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); }Thanks. That looks quite promising. But it does not compile for me: test.d(12): class test.Inner(alias outer) is used as a type test.d(12): variable test.main.i1 voids have no value
Sep 16 2007
Matti Niemenmaa Wrote:coxalan wrote:Thanks!Matti Niemenmaa Wrote:Alright, I took a closer look and this compiles: class Outer { } class Inner(alias outer) { static assert(is(typeof(outer) : Outer)); // Just a check } final Outer o1; final Outer o2; static this() { o1 = new Outer; o2 = new Outer; } void main() { auto i1 = new Inner!(o1); auto i2 = new Inner!(o1); auto i3 = new Inner!(o2); auto i4 = new Inner!(o2); }coxalan wrote:Thanks. Now I get: test.d(5): static assert is false Disclaimer: I'm quite new to D.Bruno Medeiros Wrote:Probably because he uses "Inner i[1234]" where he should use "Inner!(o[1234]) i[1234]". The easiest solution is to use "auto" on the left-hand side of the assignments.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); }Thanks. That looks quite promising. But it does not compile for me: test.d(12): class test.Inner(alias outer) is used as a type test.d(12): variable test.main.i1 voids have no value
Sep 16 2007
Matti Niemenmaa Wrote:Alright, I took a closer look and this compiles: class Outer { } class Inner(alias outer) { static assert(is(typeof(outer) : Outer)); // Just a check } final Outer o1; final Outer o2; static this() { o1 = new Outer; o2 = new Outer; } void main() { auto i1 = new Inner!(o1); auto i2 = new Inner!(o1); auto i3 = new Inner!(o2); auto i4 = new Inner!(o2); } -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) fiOne last question on this: Is it possible to do the same with D version 1? The current code comples with DMD v2.004, but with DMD 1.020 I get: forum.d(16): Error: cannot modify final variable 'o1' forum.d(17): Error: cannot modify final variable 'o2' coxalan
Sep 20 2007
coxalan wrote:Matti Niemenmaa Wrote:Make o1 and o2 const instead of final. -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) ficlass Outer { } class Inner(alias outer) { static assert(is(typeof(outer) : Outer)); // Just a check } final Outer o1; final Outer o2; static this() { o1 = new Outer; o2 = new Outer; } void main() { auto i1 = new Inner!(o1); auto i2 = new Inner!(o1); auto i3 = new Inner!(o2); auto i4 = new Inner!(o2); }One last question on this: Is it possible to do the same with D version 1? The current code comples with DMD v2.004, but with DMD 1.020 I get: forum.d(16): Error: cannot modify final variable 'o1' forum.d(17): Error: cannot modify final variable 'o2'
Sep 20 2007
Matti Niemenmaa Wrote:coxalan wrote:Thanks! ~coxalanMatti Niemenmaa Wrote:Make o1 and o2 const instead of final. -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) ficlass Outer { } class Inner(alias outer) { static assert(is(typeof(outer) : Outer)); // Just a check } final Outer o1; final Outer o2; static this() { o1 = new Outer; o2 = new Outer; } void main() { auto i1 = new Inner!(o1); auto i2 = new Inner!(o1); auto i3 = new Inner!(o2); auto i4 = new Inner!(o2); }One last question on this: Is it possible to do the same with D version 1? The current code comples with DMD v2.004, but with DMD 1.020 I get: forum.d(16): Error: cannot modify final variable 'o1' forum.d(17): Error: cannot modify final variable 'o2'
Sep 20 2007
"coxalan" <coxalan web.de> wrote in message news:fcji0p$1tos$1 digitalmars.com...Bruno Medeiros Wrote:Inner i1 = new Inner!(o1); Inner i2 = new Inner!(o1); Inner i3 = new Inner!(o2); Inner i4 = new Inner!(o2); }But it does not compile for me: test.d(12): class test.Inner(alias outer) is used as a type test.d(12): variable test.main.i1 voids have no valueChange those declarations of i1, i2... to something like: auto i1 = new Inner!(o1); auto i2 = new Inner!(o2);
Sep 16 2007