Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
July 23, 2014 Referencing structs in a foreach | ||||
---|---|---|---|---|
| ||||
I am wondering what could be the mistake. When trying to modify the member of a struct from within a foreach, the changes are gone after leaving the loop. Code: import std.stdio; void test() { struct Foo { int a; int b; } struct Bar { Foo f1; Foo f2; } Bar bar = {{10, 20}, {10, 20}}; writefln("Before => f1.a: %d, f1.b: %d - f2.a: %d, f2.b: %d\n", bar.f1.a, bar.f1.b, bar.f2.a, bar.f2.b); foreach (ref f; [bar.f1, bar.f2]) { f.a++; f.b++; } writefln("After => f1.a: %d, f1.b: %d - f2.a: %d, f2.b: %d\n", bar.f1.a, bar.f1.b, bar.f2.a, bar.f2.b); } void main() { test(); } Should print: Before => f1.a: 10, f1.b: 20 - f2.a: 10, f2.b: 20 After => f1.a: 11, f1.b: 21 - f2.a: 11, f2.b: 21 But prints: Before => f1.a: 10, f1.b: 20 - f2.a: 10, f2.b: 20 After => f1.a: 10, f1.b: 20 - f2.a: 10, f2.b: 20 Thanks, Alf |
July 23, 2014 Re: Referencing structs in a foreach | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alf | On Wednesday, 23 July 2014 at 01:31:48 UTC, Alf wrote: > foreach (ref f; [bar.f1, bar.f2]) This allocates new array and copies struct values to it (as D structs are value types). I think this should have been a compile-time error btw, it never makes sense to do ref iteration over an array literal for this very reason. Most likely you want to forced loop unrolling here and thus something like this: > import std.typetuple; > foreach (ref f; TypeTuple!(bar.f1, bar.f2)) (don't pay attention to the weird "TypeTyple" name, it lies) |
July 23, 2014 Re: Referencing structs in a foreach | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alf | Also please post any further questions to http://forum.dlang.org/group/digitalmars.D.learn instead |
July 23, 2014 Re: Referencing structs in a foreach | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | Thanks for your reply.
I figured an easier way would be to simply build an array of references:
foreach (ref f; [&bar.f1, &bar.f2])
{
f.a++;
f.b++;
}
It seems to work just fine.
Alf
On Wednesday, 23 July 2014 at 01:41:33 UTC, Dicebot wrote:
> On Wednesday, 23 July 2014 at 01:31:48 UTC, Alf wrote:
>> foreach (ref f; [bar.f1, bar.f2])
>
> This allocates new array and copies struct values to it (as D structs are value types). I think this should have been a compile-time error btw, it never makes sense to do ref iteration over an array literal for this very reason.
>
> Most likely you want to forced loop unrolling here and thus something like this:
>
>> import std.typetuple;
>> foreach (ref f; TypeTuple!(bar.f1, bar.f2))
>
> (don't pay attention to the weird "TypeTyple" name, it lies)
|
July 23, 2014 Re: Referencing structs in a foreach | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alf | On Wednesday, 23 July 2014 at 17:23:14 UTC, Alf wrote:
> Thanks for your reply.
> I figured an easier way would be to simply build an array of references:
>
> foreach (ref f; [&bar.f1, &bar.f2])
> {
> f.a++;
> f.b++;
> }
>
> It seems to work just fine.
I'd recommend using std.range.only:
foreach (ref f; only(&x, &y)) {
f.a++;
f.b++;
}
Using array literals introduces the possibility of an unnecessary heap allocation. Using only will never allocate.
|
Copyright © 1999-2021 by the D Language Foundation