digitalmars.D.learn - Facing problems with Class Properties
- d coder (40/40) Dec 10 2010 Greetings All
- Steven Schveighoffer (12/57) Dec 10 2010 is(typeof(f) : BaseClass[]) is a compile-time construct, yet you are
- d coder (23/25) Dec 10 2010 Thanks Steve for your inputs.
- d coder (9/11) Dec 10 2010 Steve
- Steven Schveighoffer (3/13) Dec 13 2010 Just use is(T == U) instead of is(T : U)
- Jesse Phillips (3/40) Dec 10 2010 typeof() and is() are compile time constructs. Change your if statements...
- Jesse Phillips (8/10) Dec 10 2010 Just realized what the issue is. You are creating code as foreach become...
- Steven Schveighoffer (4/11) Dec 10 2010 Ah, good to know :)
- d coder (43/48) Dec 10 2010 s class Bar. The static if forces the compiler to not generate this code...
- d coder (8/11) Dec 10 2010 Ah.. Now I think I understand.
- d coder (8/16) Dec 10 2010 If I got it right now, It will be possible for me to unroll the
- Jesse Phillips (9/22) Dec 10 2010 Yes, but the if statement will also be there so the code would look some...
- spir (16/72) Dec 10 2010 is class Bar. The static if forces the compiler to not generate this co...
Greetings All I am trying to compile the following D2 code. The code giving compilation issues is the "this()" function of the class Foo. The constructor basically tries to initialize all the data members of the class, of type BaseClass and of type BaseClass array. I am using class property tupleof to iterate over members of the class. Then I check the type of each member and if the member is a BaseClass array, I new all the elements of the array. Otherwise if the member is of the type BaseClass, I new it as it is. The issue is that when I try to compile the program, I get the error bug.d(10): Error: no property 'length' for type 'test.Bar' I am explicitly checking the field type, and I am making sure that the field is an array type, before looking for its length. So I am not sure why this error appears. Please guide me. Regards Cherry import std.stdio; class BaseClass { } class Bar: BaseClass { } class Foo: BaseClass { this() { foreach(i, f; this.tupleof) { if (is (typeof(f) : BaseClass[])) { for (size_t j = 0; j < f.length; ++j) { f[j] = new typeof(f[j]) (); } } if (is(typeof(f) : BaseClass)) { f = new typeof(f) (); } } } Bar instance1; Bar instance2; Bar [10] instances; } unittest { Foo foo; foo = new Foo; }
Dec 10 2010
On Fri, 10 Dec 2010 11:35:50 -0500, d coder <dlang.coder gmail.com> wrote:Greetings All I am trying to compile the following D2 code. The code giving compilation issues is the "this()" function of the class Foo. The constructor basically tries to initialize all the data members of the class, of type BaseClass and of type BaseClass array. I am using class property tupleof to iterate over members of the class. Then I check the type of each member and if the member is a BaseClass array, I new all the elements of the array. Otherwise if the member is of the type BaseClass, I new it as it is. The issue is that when I try to compile the program, I get the error bug.d(10): Error: no property 'length' for type 'test.Bar' I am explicitly checking the field type, and I am making sure that the field is an array type, before looking for its length. So I am not sure why this error appears. Please guide me. Regards Cherry import std.stdio; class BaseClass { } class Bar: BaseClass { } class Foo: BaseClass { this() { foreach(i, f; this.tupleof) { if (is (typeof(f) : BaseClass[])) { for (size_t j = 0; j < f.length; ++j) { f[j] = new typeof(f[j]) (); } } if (is(typeof(f) : BaseClass)) { f = new typeof(f) (); } } } Bar instance1; Bar instance2; Bar [10] instances; } unittest { Foo foo; foo = new Foo; }is(typeof(f) : BaseClass[]) is a compile-time construct, yet you are trying to use it at runtime. I'm not even sure how this could compile. I imagine that you could use a recursive template to deal with the tuple, but I didn't think you could use a foreach loop. Is there a reason you can't directly reference the members? After all, you are writing the class. Another thing, is(T : U) simply means T is implicitly castable to U. Due to a compiler bug, Bar[] is implicitly castable to BaseClass[]. is(T == U) ensures that the type is exact. -Steve
Dec 10 2010
Is there a reason you can't directly reference the members? =A0After all,=youare writing the class.Thanks Steve for your inputs. Actually this is part of a bigger code that I am trying to create. Though I am pretty new to D. What I have posted is a reduced code that illustrated the issue I am facing. In the actual code, I am using string mixins and there are too many classes (all derived from BaseClass) and too many class instances, and the constructor call for Bar (and other classes) is a bit more involved. There is a need to make sure that all the constructors are called in a seamless fashion. In fact, I will not be the end-user. I would just be coding the BaseClass and the mixin. The actual end-users are not supposed to be quite D-literate and I would be asking them to code something to the effect: class Foo: BaseClass { mixin(CreateInstances()); // Define your Bar and other sub-class instances here //... // More code here } Any ideas? Regards - Cherry
Dec 10 2010
Another thing, is(T : U) simply means T is implicitly castable to U. =A0D=ue toa compiler bug, Bar[] is implicitly castable to BaseClass[].Steve I realize that I am using this compiler bug as a feature. It would be kind of you to suggest me a code that would not exploit this bug. I was thinking of using something to the effect: if (__traits(isStaticArray, this.tupleof[i]) { if (is (typeof(this.tupleof[i][0]) : BaseModule)) { Regards - Cherry
Dec 10 2010
On Fri, 10 Dec 2010 20:22:52 -0500, d coder <dlang.coder gmail.com> wrote:Just use is(T == U) instead of is(T : U) -SteveAnother thing, is(T : U) simply means T is implicitly castable to U. Due to a compiler bug, Bar[] is implicitly castable to BaseClass[].Steve I realize that I am using this compiler bug as a feature. It would be kind of you to suggest me a code that would not exploit this bug. I was thinking of using something to the effect: if (__traits(isStaticArray, this.tupleof[i]) { if (is (typeof(this.tupleof[i][0]) : BaseModule)) {
Dec 13 2010
d coder Wrote:The issue is that when I try to compile the program, I get the error bug.d(10): Error: no property 'length' for type 'test.Bar' I am explicitly checking the field type, and I am making sure that the field is an array type, before looking for its length. So I am not sure why this error appears. Please guide me. Regards Cherry import std.stdio; class BaseClass { } class Bar: BaseClass { } class Foo: BaseClass { this() { foreach(i, f; this.tupleof) { if (is (typeof(f) : BaseClass[])) { for (size_t j = 0; j < f.length; ++j) { f[j] = new typeof(f[j]) (); } } if (is(typeof(f) : BaseClass)) { f = new typeof(f) (); } } } Bar instance1; Bar instance2; Bar [10] instances; } unittest { Foo foo; foo = new Foo; }typeof() and is() are compile time constructs. Change your if statements to static if.
Dec 10 2010
Jesse Phillips Wrote:typeof() and is() are compile time constructs. Change your if statements to static if.Just realized what the issue is. You are creating code as foreach becomes a static foreach when iterating a tupleof. (Yes steven it does work) This you are building code which looks like if(false) { for (size_t j = 0; j < f.length...) ... } Semantically this code is wrong as you can't take the length of f which is class Bar. The static if forces the compiler to not generate this code as it is known to be false.
Dec 10 2010
On Fri, 10 Dec 2010 15:08:34 -0500, Jesse Phillips <jessekphillips+D gmail.com> wrote:Jesse Phillips Wrote:Ah, good to know :) -Stevetypeof() and is() are compile time constructs. Change your if statements to static if.Just realized what the issue is. You are creating code as foreach becomes a static foreach when iterating a tupleof. (Yes steven it does work)
Dec 10 2010
if(false) { =A0 =A0for (size_t j =3D 0; j < f.length...) =A0 =A0... } Semantically this code is wrong as you can't take the length of f which i=s class Bar. The static if forces the compiler to not generate this code as= it is known to be false.Thanks Jesse What you are saying makes sense to me. The problem is that the following code works perfectly. I have just commented out some part and replaced it with some debug statements. The output from this code makes me believe that "is" and "typeof" do have some run-time semantics. Or is it a D2 bug. BTW I am using Digital Mars D Compiler v2.050. Regards - Puneet import std.stdio; class BaseClass { } class Bar: BaseClass { } class Foo: BaseClass { this() { foreach(i, f; this.tupleof) { if (is (typeof(this.tupleof[i]) : BaseClass[])) { writeln("Creating new objects for all ARRAY types ", this.tupleof[i].strin= gof); // for (size_t j =3D 0; j < this.tupleof[i].length; ++j) { // this.tupleof[i][j] =3D new typeof(this.tupleof[i][j]) (); // } } if (is(typeof(this.tupleof[i]) : BaseClass)) { writeln("Creating new objects for all NON-ARRAY types ", this.tupleof[i].stringof); // this.tupleof[i] =3D new typeof(this.tupleof[i]) (); } } } Bar instance1; Bar instance2; Bar [10] instances; } unittest { Foo foo; foo =3D new Foo; } // I am getting the following output // Creating new objects for all NON-ARRAY types this.instance1 // Creating new objects for all NON-ARRAY types this.instance2 // Creating new objects for all ARRAY types this.instances
Dec 10 2010
What you are saying makes sense to me. The problem is that the following code works perfectly. I have just commented out some part and replaced it with some debug statements.Ah.. Now I think I understand. This new code I have written will all be run at compile time. So in this case, the foreach statement inside the constructor would be reduced to a bunch of writeln statements at compile time and those writeln would be executed at the run time. This will not happen with the actual code since there are other typeof and is statements in there that can not be run at runtime. Did I get it right?
Dec 10 2010
Ah.. Now I think I understand. This new code I have written will all be run at compile time. So in this case, the foreach statement inside the constructor would be reduced to a bunch of writeln statements at compile time and those writeln would be executed at the run time. This will not happen with the actual code since there are other typeof and is statements in there that can not be run at runtime. Did I get it right?If I got it right now, It will be possible for me to unroll the foreach loop and the if statements in a mixin and that would work well. Or may be changing the "if" statement to "static if" would do the trick. I will give it a try. Thank you Steve and tank you Jesse for showing me the light. Regards - Cherry
Dec 10 2010
d coder Wrote:Yes, but the if statement will also be there so the code would look something like: if(true) writeln(...) if(false) writeln(...) ...Ah.. Now I think I understand. This new code I have written will all be run at compile time. So in this case, the foreach statement inside the constructor would be reduced to a bunch of writeln statements at compile time and those writeln would be executed at the run time. This will not happen with the actual code since there are other typeof and is statements in there that can not be run at runtime.If I got it right now, It will be possible for me to unroll the foreach loop and the if statements in a mixin and that would work well. Or may be changing the "if" statement to "static if" would do the trick. I will give it a try.Static if must be done so that invalid code is not generated. As for another part of what you want. Use std.range.ElementType so that you can get the type you wish to call new for: this.tupleof[i][j] = new ElementType!(this.tupleof[i])();
Dec 10 2010
On Sat, 11 Dec 2010 06:11:43 +0530 d coder <dlang.coder gmail.com> wrote:is class Bar. The static if forces the compiler to not generate this code = as it is known to be false.if(false) { =C2=A0 =C2=A0for (size_t j =3D 0; j < f.length...) =C2=A0 =C2=A0... } Semantically this code is wrong as you can't take the length of f which=ingof);=20 Thanks Jesse =20 What you are saying makes sense to me. The problem is that the following code works perfectly. I have just commented out some part and replaced it with some debug statements. =20 The output from this code makes me believe that "is" and "typeof" do have some run-time semantics. Or is it a D2 bug. BTW I am using Digital Mars D Compiler v2.050. =20 Regards - Puneet =20 import std.stdio; class BaseClass { } =20 class Bar: BaseClass { } =20 class Foo: BaseClass { this() { foreach(i, f; this.tupleof) { if (is (typeof(this.tupleof[i]) : BaseClass[])) { writeln("Creating new objects for all ARRAY types ", this.tupleof[i].str=// for (size_t j =3D 0; j < this.tupleof[i].length; ++j) { // this.tupleof[i][j] =3D new typeof(this.tupleof[i][j]) (); // } } if (is(typeof(this.tupleof[i]) : BaseClass)) { writeln("Creating new objects for all NON-ARRAY types ", this.tupleof[i].stringof); // this.tupleof[i] =3D new typeof(this.tupleof[i]) (); } } } Bar instance1; Bar instance2; Bar [10] instances; } =20 unittest { Foo foo; foo =3D new Foo; } =20 // I am getting the following output // Creating new objects for all NON-ARRAY types this.instance1 // Creating new objects for all NON-ARRAY types this.instance2 // Creating new objects for all ARRAY types this.instancesHello "d coder", Maybe this is wrong and stupid, but I have faced several times similar case= s ; meaning cases whare I perfectly knew (and D as well should have known ;= -) that a given thing was of given type, but could not access its slots. Try and downcast 'this.tupeof[i]' to the type that has a 'length'; if I'm r= ight, you're done. (I find this wrong, buggy, & ugly, but well...) Else, so= rry for the noise. Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Dec 10 2010