digitalmars.D - class design question (inner classes)
- coxalan (104/104) Sep 11 2007 Hello,
- Regan Heath (40/179) Sep 11 2007 Maybe template bolt-ins? (I'm not 100% sure I know what you want to
- coxalan (8/54) Sep 11 2007 With your code, the uint-value "degree" gets stored once for every insta...
- Regan Heath (37/57) Sep 11 2007 Make it "static" or, make it a template parameter and just use that, eg.
- coxalan (26/35) Sep 11 2007
- Regan Heath (80/131) Sep 11 2007 What about doing it manually/explicitly...
- Regan Heath (16/18) Sep 11 2007 But maybe we can get round this by using templates...
- Downs (24/72) Sep 11 2007 -----BEGIN PGP SIGNED MESSAGE-----
- Downs (15/15) Sep 11 2007 -----BEGIN PGP SIGNED MESSAGE-----
- coxalan (6/11) Sep 11 2007 No problem and thanks for your answer.
- Bruno Medeiros (7/43) Sep 12 2007 I assume correctly that A == Outer in that example above?
- Christian Kamm (15/22) Sep 11 2007 If SymmetricGroup contains only compile time constants, you could do:
- Roberto Mariottini (7/8) Sep 11 2007 type "s.Permutation" stores a reference to the object "s", which I want
- coxalan (3/13) Sep 11 2007 A static outer class will not work, because within the inner class I nee...
- coxalan (18/119) Sep 11 2007 Thanks for the code!
- Regan Heath (18/54) Sep 11 2007 Yep. At first I tried using a static inner class and I wanted to ensure...
- coxalan (7/48) Sep 15 2007 Yes, sorry for that.
Hello, I come from mathematics and I want to create some classes for _fast_ computations in certain algebraic structures (groups, fields, rings, ...). My hope is that specialization at compile time will give me an advantage over universal computer algebra systems. I want to have: 1) Objects for the algebraic base structures 2) Some type (class, struct, whatever) for the elements of this structure For example: 1) a class SymmetricGroup and 2) a class Permutation. Each instance of type 2) "belongs" to exactly one object of class 1). But this link should not be stored for each instance of 2). Instead, It should be given statically by the type. Furthermore, for convenience I really want to have overloaded operators for the objects of 2). Up to now I tried these two examples: *** 1 *** import std.stdio; class SymmetricGroup { const uint degree; this(int degreeIn) { degree = degreeIn; } struct Permutation { uint data[]; } Permutation createPermutation(uint[] dataIn) { Permutation result; result.data = dataIn; return result; } Permutation mul(Permutation a, Permutation b) { Permutation result; result.data.length = degree; foreach(int i, uint val; b.data) { result.data[i] = a.data[val]; } return result; } } void main() { SymmetricGroup s = new SymmetricGroup(3); s.Permutation a = s.createPermutation([0,2,1]); s.Permutation b = s.createPermutation([1,2,0]); s.Permutation c = s.mul(a,b); writefln("%d",c.data); } ******** The problem with this is that I don't know how to overload the *-Operator such that I can write s.Permutation c = a * b; instead of s.Permutation c = s.mul(a,b); I cannot add a method "opMul" within the struct "Permutation", because to call the method "mul" I would need a pointer to the outer class "SymmetricGroup", which I don't have. [Comment: Yes, I could write Permutation opMul(Permutation x) { Permutation result; result.data.length = data.length; foreach(int i, uint val; x.data) { result.data[i] = data[val]; } return result; } in this particular example, but in general I need information stored in the outer class 1).] *** 2 *** import std.stdio; class SymmetricGroup { const uint degree; this(int degreeIn) { degree = degreeIn; } class Permutation { uint data[]; this() { data.length = degree; } this(uint[] dataIn) { data = dataIn; } Permutation opMul(Permutation x) { return mul(this, x); } } Permutation mul(Permutation a, Permutation b) { Permutation result = new Permutation(); foreach(int i, uint val; b.data) { result.data[i] = a.data[val]; } return result; } } void main() { SymmetricGroup s = new SymmetricGroup(3); s.Permutation a = s.new Permutation([0,2,1]); s.Permutation b = s.new Permutation([1,2,0]); s.Permutation c = a * b; writefln("%d",c.data); } ******** This is definitely more elegant than the first example. But here, every object of type "s.Permutation" stores a reference to the object "s", which I want to avoid. If it was possible to instantiate the object "s" at compile time (something like static const SymmetricGroup s = new SymmetricGroup(3); ), the above mentioned references would not be needed. But unfortunately, It is not possible to instantiate objects at compile time (what's actually the reason for this?). [A final comment: I know that I could go without the class SymmetricGroup, and have only objects of type Permutation. But I really want these outer classes, to do constructions like direct products of groups, etc.] I believe that within the D template toolkit, there must be a solution for my problem, which I simply don't see. I will appreciate any hint or suggestion.
Sep 11 2007
coxalan wrote:Hello, I come from mathematics and I want to create some classes for _fast_ computations in certain algebraic structures (groups, fields, rings, ...). My hope is that specialization at compile time will give me an advantage over universal computer algebra systems. I want to have: 1) Objects for the algebraic base structures 2) Some type (class, struct, whatever) for the elements of this structure For example: 1) a class SymmetricGroup and 2) a class Permutation. Each instance of type 2) "belongs" to exactly one object of class 1). But this link should not be stored for each instance of 2). Instead, It should be given statically by the type. Furthermore, for convenience I really want to have overloaded operators for the objects of 2). Up to now I tried these two examples: *** 1 *** import std.stdio; class SymmetricGroup { const uint degree; this(int degreeIn) { degree = degreeIn; } struct Permutation { uint data[]; } Permutation createPermutation(uint[] dataIn) { Permutation result; result.data = dataIn; return result; } Permutation mul(Permutation a, Permutation b) { Permutation result; result.data.length = degree; foreach(int i, uint val; b.data) { result.data[i] = a.data[val]; } return result; } } void main() { SymmetricGroup s = new SymmetricGroup(3); s.Permutation a = s.createPermutation([0,2,1]); s.Permutation b = s.createPermutation([1,2,0]); s.Permutation c = s.mul(a,b); writefln("%d",c.data); } ******** The problem with this is that I don't know how to overload the *-Operator such that I can write s.Permutation c = a * b; instead of s.Permutation c = s.mul(a,b); I cannot add a method "opMul" within the struct "Permutation", because to call the method "mul" I would need a pointer to the outer class "SymmetricGroup", which I don't have. [Comment: Yes, I could write Permutation opMul(Permutation x) { Permutation result; result.data.length = data.length; foreach(int i, uint val; x.data) { result.data[i] = data[val]; } return result; } in this particular example, but in general I need information stored in the outer class 1).] *** 2 *** import std.stdio; class SymmetricGroup { const uint degree; this(int degreeIn) { degree = degreeIn; } class Permutation { uint data[]; this() { data.length = degree; } this(uint[] dataIn) { data = dataIn; } Permutation opMul(Permutation x) { return mul(this, x); } } Permutation mul(Permutation a, Permutation b) { Permutation result = new Permutation(); foreach(int i, uint val; b.data) { result.data[i] = a.data[val]; } return result; } } void main() { SymmetricGroup s = new SymmetricGroup(3); s.Permutation a = s.new Permutation([0,2,1]); s.Permutation b = s.new Permutation([1,2,0]); s.Permutation c = a * b; writefln("%d",c.data); } ******** This is definitely more elegant than the first example. But here, every object of type "s.Permutation" stores a reference to the object "s", which I want to avoid. If it was possible to instantiate the object "s" at compile time (something like static const SymmetricGroup s = new SymmetricGroup(3); ), the above mentioned references would not be needed. But unfortunately, It is not possible to instantiate objects at compile time (what's actually the reason for this?). [A final comment: I know that I could go without the class SymmetricGroup, and have only objects of type Permutation. But I really want these outer classes, to do constructions like direct products of groups, etc.] I believe that within the D template toolkit, there must be a solution for my problem, which I simply don't see. I will appreciate any hint or suggestion.Maybe template bolt-ins? (I'm not 100% sure I know what you want to achieve so this may be waaaay off base) class SymmetricGroup { uint degree; this(int degreeIn) { degree = degreeIn; } } class Permutation(T, int D) : T { uint data[]; this() { super(D); data.length = degree; } this(uint[] dataIn) { super(D); data = dataIn; } Permutation opMul(Permutation b) { auto result = new Permutation; foreach(int i, uint val; b.data) { result.data[i] = data[val] * b.data[val]; } return result; } } alias Permutation!(SymmetricGroup, 3) SGP; void main() { SGP a = new SGP(); SGP b = new SGP(); SGP c = a * b; } In the above you don't actually need SymmetricGroup at all, your template could just take "int D" and use that for degree, however I suspect you want to add more to SymmetricGroup? Regan
Sep 11 2007
Regan Heath Wrote:Maybe template bolt-ins? (I'm not 100% sure I know what you want to achieve so this may be waaaay off base) class SymmetricGroup { uint degree; this(int degreeIn) { degree = degreeIn; } } class Permutation(T, int D) : T { uint data[]; this() { super(D); data.length = degree; } this(uint[] dataIn) { super(D); data = dataIn; } Permutation opMul(Permutation b) { auto result = new Permutation; foreach(int i, uint val; b.data) { result.data[i] = data[val] * b.data[val]; } return result; } } alias Permutation!(SymmetricGroup, 3) SGP; void main() { SGP a = new SGP(); SGP b = new SGP(); SGP c = a * b; }With your code, the uint-value "degree" gets stored once for every instance of SGP. This is not what I want. The class SymmetricGroup should collect everything that all of its elements (the object of the class Permutation) have in common. Just imagine the same for a class TableGroup, where the multiplication-values are stored in an huge array. This table definitely should not be stored for each single element of the group.In the above you don't actually need SymmetricGroup at all, your template could just take "int D" and use that for degree, however I suspect you want to add more to SymmetricGroup?Yes, of course this is only an example which I made as short as possible. There are two reasons for this class [these are the classes of kind 1) in my first posting]: * I want to implement more kinds of groups, for example also matrix groups. All the groups should have a common interface which will be used in templated group algorithms. * There are constructions which combine two or more groups into a new one. For the implementation of such combined groups, It will be very convenient to have classes of this kind 1). coxalan
Sep 11 2007
With your code, the uint-value "degree" gets stored once for every instance of SGP. This is not what I want.Make it "static" or, make it a template parameter and just use that, eg. class SymmetricGroup { } class Permutation(T, int D) : T { uint data[]; this() { data.length = D; } this(uint[] dataIn) { data = dataIn; } Permutation opMul(Permutation b) { auto result = new Permutation; foreach(int i, uint val; b.data) { result.data[i] = data[val] * b.data[val]; } return result; } } alias Permutation!(SymmetricGroup, 3) SGP; void main() { SGP a = new SGP(); SGP b = new SGP(); SGP c = a * b; }The class SymmetricGroup should collect everything that all of its elements (the object of the class Permutation) have in common.Like .. (list please). Are they all data members or methods as well. Have you considered using mixins to mix a SymmetricGroup template containing methods/data members into Permutation.Sure, but a short example can make it hard (for us/me) to see the whole picture. :) Especially when my formal maths education stopped at high school level.In the above you don't actually need SymmetricGroup at all, your template could just take "int D" and use that for degree, however I suspect you want to add more to SymmetricGroup?Yes, of course this is only an example which I made as short as possible.There are two reasons for this class [these are the classes of kind 1) in my first posting]: * I want to implement more kinds of groups, for example also matrix groups. All the groups should have a common interface which will be used in templated group algorithms. * There are constructions which combine two or more groups into a new one. For the implementation of such combined groups, It will be very convenient to have classes of this kind 1).Ok. I think I have reached the limit of my usefulness here :) Someone else is bound to have some ideas. Regan
Sep 11 2007
Regan Heath Wrote:> The class SymmetricGroupDefinitely methods, like uint order() which returns the number of the elements of the group. For the SymmetricGroup there are no other data members, but for other Groups there could be arbitrary data members (like a big array where the multiplication results are stored).should collect everything that all of its elements (the object of the class Permutation) have in common.Like .. (list please). Are they all data members or methods as well.[...] Ok. I think I have reached the limit of my usefulness here :) Someone else is bound to have some ideas.It was my fear that I put too much technical mathematics stuff into my posting. I already put this question (in C++ form) into a mathematical internet forum, but then the OOP-design part of the discussion got stuck at a very basic level... :-) Now I rethought my question and how I can put it on a more abstract level to get out the math part. I guess my problem comes down to this point: class Outer { class Inner { [...] } [...] } main() { A a = new A(); [... initialize many a.Inner objects here ...] } Once that "a" is initialized, te reference "a" stays constant all the time. So all further references/pointers to "a" are redundant. Especially, the references to "a" stored in "a.Inner" inner objects are redundant. So if there was a way to tell the compiler that the reference a will never change, the compiler could do the optimization and skip all these inner-class-references. Now the question is: Is there currently a way to achieve a satisfying, equivalent result? If not: Should I make this a feature request? coxalan
Sep 11 2007
coxalan wrote:Regan Heath Wrote:What about doing it manually/explicitly... import std.stdio; import std.string; import std.c.stdlib; class Outer { Inner[] m_Data; uint m_Degree; this(uint d) { m_Degree = d; } Inner allocate(uint[] data) { m_Data ~= new Inner(this, data); return m_Data[$-1]; } new(uint size) { writefln("Outer new %d", size); return malloc(size); } delete(void *p) { free(p); } } class Inner { static Outer m_Outer; uint m_Data[]; this(Outer o, uint[] data = null) { m_Outer = o; m_Data.length = m_Outer.m_Degree; if (data !is null) { m_Data[0..$] = data[0..m_Data.length]; } } Inner opMul(Inner b) { Inner res = new Inner(m_Outer); foreach(int i, uint val; b.m_Data) { res.m_Data[i] = m_Data[i] * b.m_Data[i]; } return res; } new(uint size) { writefln("Inner new %d", size); return malloc(size); } delete(void *p) { free(p); } string toString() { return format("%s", m_Data); } } void main() { Outer o = new Outer(3); Inner a = o.allocate([0,1,2]); Inner b = o.allocate([1,2,3]); Inner c = a * b; writefln(c); } Of course, if you use Inner with another Outer class it will overwrite the static m_Outer and fail horribly... ReganDefinitely methods, like uint order() which returns the number of the elements of the group. For the SymmetricGroup there are no other data members, but for other Groups there could be arbitrary data members (like a big array where the multiplication results are stored).The class SymmetricGroup should collect everything that all of its elements (the object of the class Permutation) have in common.Like .. (list please). Are they all data members or methods as well.[...] Ok. I think I have reached the limit of my usefulness here :) Someone else is bound to have some ideas.It was my fear that I put too much technical mathematics stuff into my posting. I already put this question (in C++ form) into a mathematical internet forum, but then the OOP-design part of the discussion got stuck at a very basic level... :-) Now I rethought my question and how I can put it on a more abstract level to get out the math part. I guess my problem comes down to this point: class Outer { class Inner { [...] } [...] } main() { A a = new A(); [... initialize many a.Inner objects here ...] } Once that "a" is initialized, te reference "a" stays constant all the time. So all further references/pointers to "a" are redundant. Especially, the references to "a" stored in "a.Inner" inner objects are redundant. So if there was a way to tell the compiler that the reference a will never change, the compiler could do the optimization and skip all these inner-class-references. Now the question is: Is there currently a way to achieve a satisfying, equivalent result? If not: Should I make this a feature request? coxalan
Sep 11 2007
Regan Heath wrote:Of course, if you use Inner with another Outer class it will overwrite the static m_Outer and fail horribly...But maybe we can get round this by using templates... class Inner(T) { static T m_Outer; } That way, if you use say.. Inner!(Outer) a; Inner!(Outer) b; Inner!(Outer) c; Inner!(Bob) d; Inner!(Bob) e; Inner!(Fred) f; You will get a static m_Outer for each combination, thus 3 for the code above. Regan
Sep 11 2007
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 coxalan wrote:Regan Heath Wrote:I'm surprised nobody brought this up before. Yes, of course you can do this. class Outer { class Inner { [...] } } void main() { Outer foo=new Outer; auto bar=foo.new Inner; auto baz=foo.new Inner; } That what you want? :) --downs -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFG5vsZpEPJRr05fBERAtpiAJ47qu9tffXEr47OsNR3+v89i4JLEwCfU15R rUPiTTNTUCH/o/lv52Cae2M= =UmNC -----END PGP SIGNATURE-----> The class SymmetricGroupDefinitely methods, like uint order() which returns the number of the elements of the group. For the SymmetricGroup there are no other data members, but for other Groups there could be arbitrary data members (like a big array where the multiplication results are stored).should collect everything that all of its elements (the object of the class Permutation) have in common.Like .. (list please). Are they all data members or methods as well.[...] Ok. I think I have reached the limit of my usefulness here :) Someone else is bound to have some ideas.It was my fear that I put too much technical mathematics stuff into my posting. I already put this question (in C++ form) into a mathematical internet forum, but then the OOP-design part of the discussion got stuck at a very basic level... :-) Now I rethought my question and how I can put it on a more abstract level to get out the math part. I guess my problem comes down to this point: class Outer { class Inner { [...] } [...] } main() { A a = new A(); [... initialize many a.Inner objects here ...] } Once that "a" is initialized, te reference "a" stays constant all the time. So all further references/pointers to "a" are redundant. Especially, the references to "a" stored in "a.Inner" inner objects are redundant. So if there was a way to tell the compiler that the reference a will never change, the compiler could do the optimization and skip all these inner-class-references. Now the question is: Is there currently a way to achieve a satisfying, equivalent result? If not: Should I make this a feature request? coxalan
Sep 11 2007
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I'm sorry. I didn't read/understand your requirements precisely. Of course, this _will_ entail a reference to the outer class. As they say, "oops". Sorry again. --downs -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFG5vvDpEPJRr05fBERApk6AJ4mQwqMcVCiUNAp4q8bSY3O8vTK4wCgnGSD fAzOol+zuD48RTxx2aRFH+E= =5Sm8 -----END PGP SIGNATURE-----
Sep 11 2007
Downs Wrote:I'm sorry. I didn't read/understand your requirements precisely. Of course, this _will_ entail a reference to the outer class. As they say, "oops". Sorry again.No problem and thanks for your answer. As you can see in my postings, it took me some time to see what really the matter is, too: I know that in my case the reference to the outer class object will never change. So I know that all references stored in the inner class objects will be the same and are not necessary. coxalan
Sep 11 2007
coxalan wrote:Regan Heath Wrote:I assume correctly that A == Outer in that example above? Some questions: is the total number of instances of Outer constant and known at compile time? If not, I think it's impossible to do what you want. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D[...] Ok. I think I have reached the limit of my usefulness here :) Someone else is bound to have some ideas.It was my fear that I put too much technical mathematics stuff into my posting. I already put this question (in C++ form) into a mathematical internet forum, but then the OOP-design part of the discussion got stuck at a very basic level... :-) Now I rethought my question and how I can put it on a more abstract level to get out the math part. I guess my problem comes down to this point: class Outer { class Inner { [...] } [...] } main() { A a = new A(); [... initialize many a.Inner objects here ...] } Once that "a" is initialized, te reference "a" stays constant all the time. So all further references/pointers to "a" are redundant. Especially, the references to "a" stored in "a.Inner" inner objects are redundant. So if there was a way to tell the compiler that the reference a will never change, the compiler could do the optimization and skip all these inner-class-references. Now the question is: Is there currently a way to achieve a satisfying, equivalent result? If not: Should I make this a feature request? coxalan
Sep 12 2007
If it was possible to instantiate the object "s" at compile time (something like static const SymmetricGroup s = new SymmetricGroup(3); ), the above mentioned references would not be needed. But unfortunately, It is not possible to instantiate objects at compile time (what's actually the reason for this?).If SymmetricGroup contains only compile time constants, you could do: struct SymmetricGroup(int degreeIn) { const int degree = degreeIn; } struct Permutation(Group) { alias Permutation!(Group) thistype; thistype opMul(ref thistype a) { // do something with Group.degree } } void main() { alias SymmetricGroup!(3) s; Permutation!(s) a, b, c; c = a * b; }
Sep 11 2007
coxalan wrote: [...]This is definitely more elegant than the first example. But here, every object oftype "s.Permutation" stores a reference to the object "s", which I want to avoid. You can simply declare the inner class as static. This way it won't store a reference to its container class. Ciao
Sep 11 2007
Roberto Mariottini Wrote:coxalan wrote: [...]A static outer class will not work, because within the inner class I need access to the class members of the outer class. But since the outer class will stay constant, there is no need to store this reference again and again for each inner object.This is definitely more elegant than the first example. But here, every object oftype "s.Permutation" stores a reference to the object "s", which I want to avoid. You can simply declare the inner class as static. This way it won't store a reference to its container class. Ciao
Sep 11 2007
Regan Heath Wrote:What about doing it manually/explicitly...Thanks for the code!import std.stdio; import std.string; import std.c.stdlib; class Outer { Inner[] m_Data; uint m_Degree; this(uint d) { m_Degree = d; } Inner allocate(uint[] data) { m_Data ~= new Inner(this, data); return m_Data[$-1]; } new(uint size) { writefln("Outer new %d", size); return malloc(size); } delete(void *p) { free(p); } } class Inner { static Outer m_Outer; uint m_Data[]; this(Outer o, uint[] data = null) { m_Outer = o; m_Data.length = m_Outer.m_Degree; if (data !is null) { m_Data[0..$] = data[0..m_Data.length]; } } Inner opMul(Inner b) { Inner res = new Inner(m_Outer); foreach(int i, uint val; b.m_Data) { res.m_Data[i] = m_Data[i] * b.m_Data[i]; } return res; } new(uint size) { writefln("Inner new %d", size); return malloc(size); } delete(void *p) { free(p); } string toString() { return format("%s", m_Data); } } void main() { Outer o = new Outer(3); Inner a = o.allocate([0,1,2]); Inner b = o.allocate([1,2,3]); Inner c = a * b; writefln(c); }A few questions/remarks on this: * Is there a reason for overloading new and delete besides that you want to display the size of the objects? * Why the member data Inner[] m_Data; in the outer class? By this no links are stored in the Outer objects any more, but now the Inner object stores links, so nothing is won. But in my opinion this line can simply be dropped. (Of course the other line where the links actually get stored must then be modified, too.) * To execute m_Outer = o; always when a new Inner object is created is a little overhead ;-).Of course, if you use Inner with another Outer class it will overwrite the static m_Outer and fail horribly...But maybe we can get round this by using templates... class Inner(T) { static T m_Outer; } That way, if you use say.. Inner!(Outer) a; Inner!(Outer) b; Inner!(Outer) c; Inner!(Bob) d; Inner!(Bob) e; Inner!(Fred) f; You will get a static m_Outer for each combination, thus 3 for the code above.But I guess it is still not possible to have Outer a; Outer b; and then Inner objects of "a" as well as of "b". With standard D inner classes, that would be no problem. Greetings, coxalan
Sep 11 2007
coxalan wrote:Regan Heath Wrote:No problem.What about doing it manually/explicitly...Thanks for the code!A few questions/remarks on this: * Is there a reason for overloading new and delete besides that you want to display the size of the objects?Yep. At first I tried using a static inner class and I wanted to ensure it made a difference to the size.* Why the member data Inner[] m_Data; in the outer class? By this no links are stored in the Outer objects any more, but now the Inner object stores links, so nothing is won. But in my opinion this line can simply be dropped. (Of course the other line where the links actually get stored must then be modified, too.)I think I put that there because you mentioned something about needing to know how many Inner classes the Outer class was handling, it can be replaced with an int :)* To execute m_Outer = o; always when a new Inner object is created is a little overhead ;-).:)No, if both Outer and Inner are the same type for both "a" and "b" it won't work because the m_Outer will be overwritten with each new Inner.Of course, if you use Inner with another Outer class it will overwrite the static m_Outer and fail horribly...But maybe we can get round this by using templates... class Inner(T) { static T m_Outer; } That way, if you use say.. Inner!(Outer) a; Inner!(Outer) b; Inner!(Outer) c; Inner!(Bob) d; Inner!(Bob) e; Inner!(Fred) f; You will get a static m_Outer for each combination, thus 3 for the code above.But I guess it is still not possible to have Outer a; Outer b; and then Inner objects of "a" as well as of "b".With standard D inner classes, that would be no problem.True, but I can't see how it's possible to get what you want with inner classes. If the inner class is "static" then it has no outer reference, but it also cannot access any non-static members of outer either. If it's not static then it has an outer reference. What you actually want is for the outer reference to be a static member of the outer class, but then how can the inner class find it, unless it has a reference to the outer class. Regan
Sep 11 2007
Bruno Medeiros Wrote:coxalan wrote:Yes, sorry for that. Above I corrected that line.Regan Heath Wrote:I assume correctly that A == Outer in that example above?[...] Ok. I think I have reached the limit of my usefulness here :) Someone else is bound to have some ideas.It was my fear that I put too much technical mathematics stuff into my posting. I already put this question (in C++ form) into a mathematical internet forum, but then the OOP-design part of the discussion got stuck at a very basic level... :-) Now I rethought my question and how I can put it on a more abstract level to get out the math part. I guess my problem comes down to this point: class Outer { class Inner { [...] } [...] } main() { Outer a = new Outer(); [... initialize many a.Inner objects here ...] } Once that "a" is initialized, the reference "a" stays constant all the time. So all further references/pointers to "a" are redundant. Especially, the references to "a" stored in "a.Inner" inner objects are redundant. So if there was a way to tell the compiler that the reference "a" will never change, the compiler could do the optimization and skip all these inner-class-references. Now the question is: Is there currently a way to achieve a satisfying, equivalent result? If not: Should I make this a feature request? coxalanSome questions: is the total number of instances of Outer constant and known at compile time? If not, I think it's impossible to do what you want.Yes, the number is known at compile time. I guess I will start a new thread now that I understand my problem much clearer. coxalan
Sep 15 2007