Thread overview
enumerating member offsetofs via foreach over members-tuple
Nov 14, 2008
Denis Koroskin
Nov 14, 2008
Denis Koroskin
Nov 19, 2008
deadimp
Nov 19, 2008
Denis Koroskin
Nov 14, 2008
Denis Koroskin
Nov 14, 2008
bearophile
Nov 15, 2008
Denis Koroskin
Nov 14, 2008
Frits van Bommel
Nov 15, 2008
Denis Koroskin
November 14, 2008
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?
November 14, 2008
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!();
}
November 14, 2008
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.
November 14, 2008
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
November 14, 2008
"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


November 14, 2008
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);
}
-----
November 15, 2008
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!
November 15, 2008
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.
November 19, 2008
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.
November 19, 2008
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