www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting all struct members and values with introspection avoiding

reply ParticlePeter <ParticlePeter gmx.de> writes:
I am logging arbitrary POD struct types with member names and 
data:

void printStructInfo( T )( T info ) {
   foreach( i, A; typeof( T.tupleof )) {
     enum attribName = T.tupleof[i].stringof;
     writefln( "%s : %s", attribName, mixin( "info." ~ attribName 
));
   }
}

Is there is some other way to evaluate info.attribName without 
using string mixins?

Cheers, PP
May 01 2016
next sibling parent reply "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Sun, May 01, 2016 at 09:42:37AM +0000, ParticlePeter via Digitalmars-d-learn
wrote:
 I am logging arbitrary POD struct types with member names and data:
 
 void printStructInfo( T )( T info ) {
   foreach( i, A; typeof( T.tupleof )) {
     enum attribName = T.tupleof[i].stringof;
     writefln( "%s : %s", attribName, mixin( "info." ~ attribName ));
   }
 }
 
 Is there is some other way to evaluate info.attribName without using
 string mixins?
[...] Using typeof(T.tupleof) seems a bit circuitous. Here's how I'd do it: void printStructInfo( T )( T info ) { import std.stdio : writefln; foreach (memb; __traits(allMembers, T)) { writefln("%s: %s", memb, __traits(getMember, info, memb)); } } (For structs that have members other than data fields, you'll need a static if to filter out non-value members, but this should get you started.) T -- 2+2=4. 2*2=4. 2^2=4. Therefore, +, *, and ^ are the same operation.
May 01 2016
next sibling parent ParticlePeter <ParticlePeter gmx.de> writes:
On Sunday, 1 May 2016 at 10:13:47 UTC, H. S. Teoh wrote:
 On Sun, May 01, 2016 at 09:42:37AM +0000, ParticlePeter via 
 Digitalmars-d-learn wrote:
 I am logging arbitrary POD struct types with member names and 
 data:
 
 void printStructInfo( T )( T info ) {
   foreach( i, A; typeof( T.tupleof )) {
     enum attribName = T.tupleof[i].stringof;
     writefln( "%s : %s", attribName, mixin( "info." ~ 
 attribName ));
   }
 }
 
 Is there is some other way to evaluate info.attribName without 
 using string mixins?
[...] Using typeof(T.tupleof) seems a bit circuitous. Here's how I'd do it: void printStructInfo( T )( T info ) { import std.stdio : writefln; foreach (memb; __traits(allMembers, T)) { writefln("%s: %s", memb, __traits(getMember, info, memb)); } } (For structs that have members other than data fields, you'll need a static if to filter out non-value members, but this should get you started.) T
Thanks, I was searching for that! The given example is a simplification of my code. I do examine each member separately and treat accordingly, but eventually used the mixin version to get the build-in type values.
May 01 2016
prev sibling parent mw <m g.c> writes:
On Sunday, 1 May 2016 at 10:13:47 UTC, H. S. Teoh wrote:
 Using typeof(T.tupleof) seems a bit circuitous. Here's how I'd 
 do it:

 	void printStructInfo( T )( T info ) {
 		import std.stdio : writefln;
 		foreach (memb; __traits(allMembers, T)) {
 			writefln("%s: %s", memb,
 				__traits(getMember, info, memb));
 		}
 	}

 (For structs that have members other than data fields, you'll 
 need a static if to filter out non-value members, but this 
 should get you started.)
How to check `isAlias`? e.g. ``` struct foo { int bar; alias bar baz; } ``` I want to filter out baz (right now, it's included).
Sep 28 2023
prev sibling parent reply cc <cc nevernet.com> writes:
On Sunday, 1 May 2016 at 09:42:37 UTC, ParticlePeter wrote:
 I am logging arbitrary POD struct types with member names and 
 data:

 void printStructInfo( T )( T info ) {
   foreach( i, A; typeof( T.tupleof )) {
     enum attribName = T.tupleof[i].stringof;
     writefln( "%s : %s", attribName, mixin( "info." ~ 
 attribName ));
   }
 }

 Is there is some other way to evaluate info.attribName without 
 using string mixins?

 Cheers, PP
If you have `T info`, T.tupleof[n] will always match up with info.tupleof[n]. You can think of `info.tupleof[n]` as being rewritten by the compiler in-place as info.whateverFieldThatIs. You might try this version (note the double {{ }} with static foreach): ```d void printStructInfo( T )( T info ) { static foreach( i, A; info.tupleof ) {{ enum attribName = T.tupleof[i].stringof; writefln( "%s : %s", attribName, info.tupleof[i] ); }} } ``` Be advised that T.tupleof and __traits(allMembers, T) return two different sets of things. allMembers will probably get you a lot of stuff you don't want and will need to write checks to avoid. Using .tupleof is a perfectly acceptable practice.
Oct 05 2023
parent reply mw <mw g.c> writes:
On Thursday, 5 October 2023 at 21:41:38 UTC, cc wrote:
 If you have `T info`, T.tupleof[n] will always match up with 
 info.tupleof[n].  You can think of `info.tupleof[n]` as being 
 rewritten by the compiler in-place as info.whateverFieldThatIs. 
  You might try this version (note the double {{ }} with static 
 foreach):
 ```d
 void printStructInfo( T )( T info ) {
 	static foreach( i, A; info.tupleof ) {{
 		enum attribName = T.tupleof[i].stringof;
 		writefln( "%s : %s", attribName, info.tupleof[i] );
 	}}
 }
 ```

 Be advised that T.tupleof and __traits(allMembers, T) return 
 two different sets of things.  allMembers will probably get you 
 a lot of stuff you don't want and will need to write checks to 
 avoid.  Using .tupleof is a perfectly acceptable practice.
Thanks, this version does not include the alias.
Oct 05 2023
parent user1234 <user1234 12.de> writes:
On Thursday, 5 October 2023 at 22:24:06 UTC, mw wrote:
 On Thursday, 5 October 2023 at 21:41:38 UTC, cc wrote:
 If you have `T info`, T.tupleof[n] will always match up with 
 info.tupleof[n].  You can think of `info.tupleof[n]` as being 
 rewritten by the compiler in-place as 
 info.whateverFieldThatIs.  You might try this version (note 
 the double {{ }} with static foreach):
 ```d
 void printStructInfo( T )( T info ) {
 	static foreach( i, A; info.tupleof ) {{
 		enum attribName = T.tupleof[i].stringof;
 		writefln( "%s : %s", attribName, info.tupleof[i] );
 	}}
 }
 ```

 Be advised that T.tupleof and __traits(allMembers, T) return 
 two different sets of things.  allMembers will probably get 
 you a lot of stuff you don't want and will need to write 
 checks to avoid.  Using .tupleof is a perfectly acceptable 
 practice.
Thanks, this version does not include the alias.
Be aware however that `.tupleof[i]` create at compile time the tuple, just to read a single element, when finally just one is required.
Oct 05 2023