second draft: add Bitfields to D

Walter Bright newshound2 at digitalmars.com
Tue Apr 30 03:14:33 UTC 2024


On 4/29/2024 5:04 AM, Timon Gehr wrote:
> You are breaking even simple patterns like
> `foreach(ref field;s.tupleof){ }`.

Let's see what happens.

```
import core.stdc.stdio;

struct S { int a; int b; enum int c = 3; int d:3, e:4; }

void main()
{
     S s;
     s.a = 1;
     s.b = 2;
     s.d = 3;
     s.e = 4;
     foreach (ref f; s.tupleof) { printf("%d\n", f); }
}
```
which prints:
```
1
2
3
4
```
What is going on here? foreach over a tuple is not really a loop. It's a 
shorthand for a sequence of statements that the compiler unrolls the "loop" 
into. When the compiler sees a 'ref' for something that cannot have its address 
taken, it ignores the 'ref'. This can also be seen with:
```
foreach(ref i; 0 .. 10) { }
```
which works. You can see this in action when compiling with -vasm.

Additionally, for such unrolled loops the 'f' is not a loop variable. It is a 
new variable created for each unroll of the loop. You can see this with:
```
import core.stdc.stdio;

struct S { int a; int b; enum int c = 3; int d:3, e:4; }

void main()
{
     S s;
     s.a = 1;
     s.b = 2;
     s.d = 3;
     s.e = 4;
     foreach (ref f; s.tupleof) { foo(f); }
     foreach (ref f; s.tupleof) { printf("%d\n", f); }
}

void foo(ref int f)
{
     printf("f: %d\n", f);
     ++f;
}
```
where s.a and s.b get incremented, but s.d and s.e do not.

I do not recall exactly why this `ref` behavior was done for foreach, but it was 
either a mistake or was done precisely to make generic code work. Either way, 
what's done is done, and there doesn't seem to be much point in breaking it.


More information about the dip.development mailing list