Thread overview
Facing problems with Class Properties
Dec 10, 2010
d coder
Dec 11, 2010
d coder
Dec 11, 2010
d coder
Dec 10, 2010
Jesse Phillips
December 10, 2010
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;
}


December 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
December 10, 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.
December 11, 2010
> Is there a reason you can't directly reference the members?  After all, you are 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
December 11, 2010
> Another 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)) {

Regards
- Cherry
December 13, 2010
On Fri, 10 Dec 2010 20:22:52 -0500, d coder <dlang.coder@gmail.com> wrote:

>> Another 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)) {


Just use is(T == U) instead of is(T : U)

-Steve