www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - enumerating member offsetofs via foreach over members-tuple

reply "Denis Koroskin" <2korden gmail.com> writes:
I'm doing some meta stuff and came across a few problems.

First of is described here:  
http://d.puremagic.com/issues/show_bug.cgi?id=2454

Second one is slightly different and this time I am less sure whether it  
is a bug.
The following code is indetended to print offsets of all its members:

struct Test
{
     short s;
     int i;
     float f;
     double d;

     void test()
     {
         writefln("expected output:");
         writefln( cast(char*)&s - cast(char*)this ); //  
writefln(s.offsetof);
         writefln( cast(char*)&i - cast(char*)this ); //  
writefln(i.offsetof);
         writefln( cast(char*)&f - cast(char*)this ); //  
writefln(f.offsetof);
         writefln( cast(char*)&d - cast(char*)this ); //  
writefln(d.offsetof);

         writefln("actual output:");
         foreach (m; this.tupleof) {
             // writefln(m.offsetof); // Error: no property 'offsetof' for  
type 'short'
             writefln( cast(char*)&m - cast(char*)this);
         }
     }
}

expected output:
0
4
8
16

actual output:
-52
-48
-44
-40

Am I doing something wrong?
Nov 14 2008
next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Fri, 14 Nov 2008 23:55:08 +0300, Denis Koroskin <2korden gmail.com>  
wrote:

 I'm doing some meta stuff and came across a few problems.

 First of is described here:  
 http://d.puremagic.com/issues/show_bug.cgi?id=2454

 Second one is slightly different and this time I am less sure whether it  
 is a bug.
 The following code is indetended to print offsets of all its members:

 struct Test
 {
      short s;
      int i;
      float f;
      double d;

      void test()
      {
          writefln("expected output:");
          writefln( cast(char*)&s - cast(char*)this ); //  
 writefln(s.offsetof);
          writefln( cast(char*)&i - cast(char*)this ); //  
 writefln(i.offsetof);
          writefln( cast(char*)&f - cast(char*)this ); //  
 writefln(f.offsetof);
          writefln( cast(char*)&d - cast(char*)this ); //  
 writefln(d.offsetof);

          writefln("actual output:");
          foreach (m; this.tupleof) {
              // writefln(m.offsetof); // Error: no property 'offsetof'  
 for type 'short'
              writefln( cast(char*)&m - cast(char*)this);
          }
      }
 }

 expected output:
 0
 4
 8
 16

 actual output:
 -52
 -48
 -44
 -40

 Am I doing something wrong?

One more found, can anyone explain error message, please? Is it valid or not? template Test() { void test() { foreach (m; this.tupleof) { writefln(typeof(m).stringof); // test.d(8): function test.B.Test!().test cannot access frame of function test } } } struct A { float i; mixin Test!(); } struct B { A a; mixin Test!(); }
Nov 14 2008
parent deadimp <deadimp gmail.com> writes:
Denis Koroskin Wrote:

 On Fri, 14 Nov 2008 23:55:08 +0300, Denis Koroskin <2korden gmail.com>  
 wrote:
 
 One more found, can anyone explain error message, please? Is it valid or  
 not?
 
 template Test()
 {
      void test()
      {
          foreach (m; this.tupleof) {
              writefln(typeof(m).stringof); // test.d(8): function  
 test.B.Test!().test cannot access frame of function test
          }
      }
 }
 
 struct A
 {
      float i;
      mixin Test!();
 }
 
 struct B
 {
      A a;
      mixin Test!();
 }

Which compiler are you using? I tested this on codepad.org and it worked.
Nov 18 2008
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Fri, 14 Nov 2008 23:55:08 +0300, Denis Koroskin <2korden gmail.com>  
wrote:

 I'm doing some meta stuff and came across a few problems.

 First of is described here:  
 http://d.puremagic.com/issues/show_bug.cgi?id=2454

 Second one is slightly different and this time I am less sure whether it  
 is a bug.
 The following code is indetended to print offsets of all its members:

 struct Test
 {
      short s;
      int i;
      float f;
      double d;

      void test()
      {
          writefln("expected output:");
          writefln( cast(char*)&s - cast(char*)this ); //  
 writefln(s.offsetof);
          writefln( cast(char*)&i - cast(char*)this ); //  
 writefln(i.offsetof);
          writefln( cast(char*)&f - cast(char*)this ); //  
 writefln(f.offsetof);
          writefln( cast(char*)&d - cast(char*)this ); //  
 writefln(d.offsetof);

          writefln("actual output:");
          foreach (m; this.tupleof) {
              // writefln(m.offsetof); // Error: no property 'offsetof'  
 for type 'short'
              writefln( cast(char*)&m - cast(char*)this);
          }
      }
 }

 expected output:
 0
 4
 8
 16

 actual output:
 -52
 -48
 -44
 -40

 Am I doing something wrong?

The following works but ... struct Test { short s; int i; float f; double d; void test() { foreach (i,m; this.tupleof) { // writefln(m.offsetof); writefln(cast(char*)&mixin(this.tupleof[i].stringof) - cast(char*)this); } } } There is definitely a room for improvement.
Nov 14 2008
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Denis Koroskin:
 First of is described here:  
 http://d.puremagic.com/issues/show_bug.cgi?id=2454

Just a note, the result is correct if you replace this line: writefln(typeof(m).stringof); With: writefln(typeid(typeof(m))); Bye, bearophile
Nov 14 2008
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Denis Koroskin" wrote
 I'm doing some meta stuff and came across a few problems.

 First of is described here: 
 http://d.puremagic.com/issues/show_bug.cgi?id=2454

Bug reports without actual errors listed in them (i.e. 'try this and see what happens') will probably be ignored. It would do you good to show what the errors are.
 Second one is slightly different and this time I am less sure whether it 
 is a bug.
 The following code is indetended to print offsets of all its members:

 struct Test
 {
     short s;
     int i;
     float f;
     double d;

     void test()
     {
         writefln("expected output:");
         writefln( cast(char*)&s - cast(char*)this ); // 
 writefln(s.offsetof);
         writefln( cast(char*)&i - cast(char*)this ); // 
 writefln(i.offsetof);
         writefln( cast(char*)&f - cast(char*)this ); // 
 writefln(f.offsetof);
         writefln( cast(char*)&d - cast(char*)this ); // 
 writefln(d.offsetof);

         writefln("actual output:");
         foreach (m; this.tupleof) {
             // writefln(m.offsetof); // Error: no property 'offsetof' for 
 type 'short'
             writefln( cast(char*)&m - cast(char*)this);
         }
     }
 }

 expected output:
 0
 4
 8
 16

 actual output:
 -52
 -48
 -44
 -40

 Am I doing something wrong?

Yes, in the code: foreach(m; this.tupleof) m is a variable local to the for loop, not a reference to the actual tuple member. I'm not sure foreach(ref m; this.tupleof) will work, I haven't done much with tuples. But certainly if ref m does work, the writefln( cast(char *)&m - cast(char *)this); should be accurate. But m.offsetof probably won't, since at that point, m is simply a ref local variable, not a member of the struct. I think possibly the only way offsetof works is in the form aggregate.member.offsetof. I could be totally wrong. -Steve
Nov 14 2008
prev sibling next sibling parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Denis Koroskin wrote:
 Am I doing something wrong?

As was mentioned, 'm' is just a local variable once inside the loop. This works though: ----- foreach (i, m; this.tupleof) { writefln(this.tupleof[i].offsetof); } -----
Nov 14 2008
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
15.11.08 в 00:30 Steven Schveighoffer в своём письме
писал(а):

 "Denis Koroskin" wrote
 I'm doing some meta stuff and came across a few problems.

 First of is described here:
 http://d.puremagic.com/issues/show_bug.cgi?id=2454

Bug reports without actual errors listed in them (i.e. 'try this and see what happens') will probably be ignored. It would do you good to show what the errors are.
 Second one is slightly different and this time I am less sure whether it
 is a bug.
 The following code is indetended to print offsets of all its members:

 struct Test
 {
     short s;
     int i;
     float f;
     double d;

     void test()
     {
         writefln("expected output:");
         writefln( cast(char*)&s - cast(char*)this ); //
 writefln(s.offsetof);
         writefln( cast(char*)&i - cast(char*)this ); //
 writefln(i.offsetof);
         writefln( cast(char*)&f - cast(char*)this ); //
 writefln(f.offsetof);
         writefln( cast(char*)&d - cast(char*)this ); //
 writefln(d.offsetof);

         writefln("actual output:");
         foreach (m; this.tupleof) {
             // writefln(m.offsetof); // Error: no property 'offsetof'  
 for
 type 'short'
             writefln( cast(char*)&m - cast(char*)this);
         }
     }
 }

 expected output:
 0
 4
 8
 16

 actual output:
 -52
 -48
 -44
 -40

 Am I doing something wrong?

Yes, in the code: foreach(m; this.tupleof) m is a variable local to the for loop, not a reference to the actual tuple member. I'm not sure foreach(ref m; this.tupleof) will work, I haven't done much with tuples. But certainly if ref m does work, the writefln( cast(char *)&m - cast(char *)this); should be accurate. But m.offsetof probably won't, since at that point, m is simply a ref local variable, not a member of the struct. I think possibly the only way offsetof works is in the form aggregate.member.offsetof. I could be totally wrong. -Steve

Ooops, sorry. I *hate* when others do like this but accidentially fell to the same trap. Thank you!
Nov 14 2008
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
15.11.08 в 01:47 Frits van Bommel в своём письме писал(а):

 Denis Koroskin wrote:
 Am I doing something wrong?

As was mentioned, 'm' is just a local variable once inside the loop. This works though: ----- foreach (i, m; this.tupleof) { writefln(this.tupleof[i].offsetof); } -----

Ah, you are right. I knew I made a mistake somewhere! Thank you.
Nov 14 2008
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Wed, 19 Nov 2008 08:12:21 +0300, deadimp <deadimp gmail.com> wrote:

 Denis Koroskin Wrote:

 On Fri, 14 Nov 2008 23:55:08 +0300, Denis Koroskin <2korden gmail.com>
 wrote:

 One more found, can anyone explain error message, please? Is it valid or
 not?

 template Test()
 {
      void test()
      {
          foreach (m; this.tupleof) {
              writefln(typeof(m).stringof); // test.d(8): function
 test.B.Test!().test cannot access frame of function test
          }
      }
 }

 struct A
 {
      float i;
      mixin Test!();
 }

 struct B
 {
      A a;
      mixin Test!();
 }

Which compiler are you using? I tested this on codepad.org and it worked.

Sorry, I forgot to mention - it's 2.020
Nov 19 2008