digitalmars.D.learn - Accessing part of a struct in an easy way
- Paolo Invernizzi (21/21) Jul 03 2017 I've struct like that:
- vit (31/52) Jul 03 2017 //https://dpaste.dzfl.pl/d59469c264b2
- Paolo Invernizzi (5/37) Jul 03 2017 Thanks for your solution, Vic!
- =?UTF-8?Q?Ali_=c3=87ehreli?= (40/42) Jul 03 2017 I had difficulty understanding the requirements. For example, it's not
- Paolo Invernizzi (6/14) Jul 03 2017 Thanks Ali,
I've struct like that: struct Foo { int a_1; float a_2; string a_3; string b_1; double b_2; } I would like to transparently access that like: foo.a.first foo.b.second = "baz"; with an helper like: auto a(...) { ... } auto b(...) { ... } that can be used also in functions that are expecting it: void worksOnA( .... ) { } void worksOnB( .... ) { } auto foo = Foo( ... ) foo.a.worksOnA(); foo.b.worksOnB(); But I'm struggling in finding a good way to do it... Suggestions? Thanks! /Paolo
Jul 03 2017
On Monday, 3 July 2017 at 13:53:45 UTC, Paolo Invernizzi wrote:I've struct like that: struct Foo { int a_1; float a_2; string a_3; string b_1; double b_2; } I would like to transparently access that like: foo.a.first foo.b.second = "baz"; with an helper like: auto a(...) { ... } auto b(...) { ... } that can be used also in functions that are expecting it: void worksOnA( .... ) { } void worksOnB( .... ) { } auto foo = Foo( ... ) foo.a.worksOnA(); foo.b.worksOnB(); But I'm struggling in finding a good way to do it... Suggestions? Thanks! /Paolo//https://dpaste.dzfl.pl/d59469c264b2 import std.algorithm : map, copy, equal; import std.range : iota; struct Foo { int[3] a; string[2] b; } ref T first(R : T[], T)(ref R x,){return x[0];} ref T second(R : T[], T)(ref R x){return x[1];} void worksOnA(R : int[N], size_t N)(ref R r) { iota(1, N+1) .map!(x => cast(int)x*2) .copy(r[]); } void worksOnB(string[] r) { } void main(){ auto foo = Foo(); foo.a.first = 1; foo.a.second = 2; assert(foo.a.first == 1); assert(foo.a.second == 2); foo.b.second = "test"; assert(foo.b.first == ""); assert(foo.b.second == "test"); foo.a.worksOnA(); assert(foo.a[].equal([2, 4, 6])); }
Jul 03 2017
On Monday, 3 July 2017 at 16:41:51 UTC, vit wrote:On Monday, 3 July 2017 at 13:53:45 UTC, Paolo Invernizzi wrote:Thanks for your solution, Vic! It's not exactly the same, as first and second should be struct with partial fields from Foo, of different types. /Paolo[...]//https://dpaste.dzfl.pl/d59469c264b2 import std.algorithm : map, copy, equal; import std.range : iota; struct Foo { int[3] a; string[2] b; } ref T first(R : T[], T)(ref R x,){return x[0];} ref T second(R : T[], T)(ref R x){return x[1];} void worksOnA(R : int[N], size_t N)(ref R r) { iota(1, N+1) .map!(x => cast(int)x*2) .copy(r[]); } void worksOnB(string[] r) { } void main(){ auto foo = Foo(); foo.a.first = 1; foo.a.second = 2; assert(foo.a.first == 1); assert(foo.a.second == 2); foo.b.second = "test"; assert(foo.b.first == ""); assert(foo.b.second == "test"); foo.a.worksOnA(); assert(foo.a[].equal([2, 4, 6])); }
Jul 03 2017
hOn 07/03/2017 10:13 AM, Paolo Invernizzi wrote:It's not exactly the same, as first and second should be struct with partial fields from Foo, of different types.I had difficulty understanding the requirements. For example, it's not clear whether you want the literal "first" and "second" names. If you want to magically use part of a struct as a separate type, it's impossible in a strongly typed language like D. However, you have low-level options that allow you to lay data almost in any way you want. Obviously, if you have access to Foo's source and it's feasible to change it, you can do this: struct Foo { A a; B b; } Assuming that it's not possible, you can cast addresses of parts of the struct as addresses of other types. Compiles but not tested: struct Foo { int a_1; float a_2; string a_3; string b_1; double b_2; } struct A { int a_1; float a_2; string a_3; } struct B { string b_1; double b_2; } auto ref a(ref Foo foo) { return *cast(A*)&foo.a_1; } auto ref b(ref Foo foo) { return *cast(B*)&foo.b_1; } void worksOnA(ref A a) { } void worksOnB(ref B b) { } void main() { auto foo = Foo(); foo.a.worksOnA(); foo.b.worksOnB(); } Ali
Jul 03 2017
On Monday, 3 July 2017 at 17:30:51 UTC, Ali Çehreli wrote:hOn 07/03/2017 10:13 AM, Paolo Invernizzi wrote:Thanks Ali, I'm doing something similar, with inout ref in the b function: I'll stick with that. Thanks again to all! /Paolo[...]struct with[...]I had difficulty understanding the requirements. For example, it's not clear whether you want the literal "first" and "second" names. [...]
Jul 03 2017