www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How get struct value by member name string ?

reply John Xu <728308756 qq.com> writes:
I saw ddbc 
(https://github.com/buggins/ddbc/blob/master/source/ddbc/pods.d) 
uses

     static if (__traits(compiles, (typeof(__traits(getMember, T, 
m))))) {
         __traits(getMember, T, m)
     }

But for my experience, above code sometimes/somewhere works, 
sometimes/somewhere just doesn't:

     Error: variable `column` cannot be read at compile time

Is there any friend can explain some more details?
May 29 2023
parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Monday, 29 May 2023 at 09:35:11 UTC, John Xu wrote:
     Error: variable `column` cannot be read at compile time
you should generally getMember on a variable T t; __traits(getMember, t, "name") like that, that's as if you wrote t.name
May 29 2023
parent reply John Xu <728308756 qq.com> writes:
On Monday, 29 May 2023 at 11:21:11 UTC, Adam D Ruppe wrote:
 On Monday, 29 May 2023 at 09:35:11 UTC, John Xu wrote:
     Error: variable `column` cannot be read at compile time
you should generally getMember on a variable T t; __traits(getMember, t, "name") like that, that's as if you wrote t.name
It seems I can't use variable as member name: struct T {int a; string name;} T t; string s = "name"; writeln(__traits(getMember, t, s)); Above code fails to compile. Any help?
May 29 2023
parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Tue, May 30, 2023 at 01:24:46AM +0000, John Xu via Digitalmars-d-learn wrote:
 On Monday, 29 May 2023 at 11:21:11 UTC, Adam D Ruppe wrote:
 On Monday, 29 May 2023 at 09:35:11 UTC, John Xu wrote:
     Error: variable `column` cannot be read at compile time
you should generally getMember on a variable T t; __traits(getMember, t, "name") like that, that's as if you wrote t.name
It seems I can't use variable as member name: struct T {int a; string name;} T t; string s = "name"; writeln(__traits(getMember, t, s)); Above code fails to compile. Any help?
Short answer: `s` must be known at compile-time. Or more precisely, known at the time of template expansion. In this case, use `enum`: enum s = "name"; Long answer: https://wiki.dlang.org/Compile-time_vs._compile-time T -- Which is worse: ignorance or apathy? Who knows? Who cares? -- Erich Schubert
May 29 2023
parent reply John Xu <728308756 qq.com> writes:
On Tuesday, 30 May 2023 at 01:33:54 UTC, H. S. Teoh wrote:
 On Tue, May 30, 2023 at 01:24:46AM +0000, John Xu via 
 Digitalmars-d-learn wrote:
 On Monday, 29 May 2023 at 11:21:11 UTC, Adam D Ruppe wrote:
 On Monday, 29 May 2023 at 09:35:11 UTC, John Xu wrote:
     Error: variable `column` cannot be read at compile time
you should generally getMember on a variable T t; __traits(getMember, t, "name") like that, that's as if you wrote t.name
It seems I can't use variable as member name: struct T {int a; string name;} T t; string s = "name"; writeln(__traits(getMember, t, s)); Above code fails to compile. Any help?
Short answer: `s` must be known at compile-time. Or more precisely, known at the time of template expansion. In this case, use `enum`: enum s = "name"; Long answer: https://wiki.dlang.org/Compile-time_vs._compile-time T
How to put above enum as a function parameter? Following code wouldn't work: string getTMember(T t, enum string memberName) { return __traits(getMember, t, memberName); } My database table is very wide, with many columns. Above ddbc allows a struct to map db returned data. Then if I want a member's value to show in vibe.d template, how do I use a function to get it?
May 30 2023
next sibling parent drug007 <drug2004 bk.ru> writes:
30.05.2023 11:46, John Xu пишет:
 
 
 How to put above enum as a function parameter? Following code wouldn't 
 work:
 
      string getTMember(T t, enum string memberName) {
          return __traits(getMember, t, memberName);
      }
 
 My database table is very wide, with many columns. Above ddbc allows a 
 struct
 to map db returned data. Then if I want a member's value to show in 
 vibe.d template,
 how do I use a function to get it?
This works for me: ```D import std; void main() { struct T {int a; string name;} auto t = T(12, "got by member name"); enum s = "name"; writeln(__traits(getMember, t, s)); } ```
May 30 2023
prev sibling next sibling parent reply bauss <jacobbauss gmail.com> writes:
On Tuesday, 30 May 2023 at 08:46:43 UTC, John Xu wrote:
 How to put above enum as a function parameter? Following code 
 wouldn't work:

     string getTMember(T t, enum string memberName) {
         return __traits(getMember, t, memberName);
     }

 ...
As simple as this: ``` string getTMember(T t, string memberName)() { return __traits(getMember, t, memberName); } ... writeln(getTMember!(t, "...")); ```
May 30 2023
parent bauss <jacobbauss gmail.com> writes:
On Tuesday, 30 May 2023 at 15:24:21 UTC, bauss wrote:
 On Tuesday, 30 May 2023 at 08:46:43 UTC, John Xu wrote:
 How to put above enum as a function parameter? Following code 
 wouldn't work:

     string getTMember(T t, enum string memberName) {
         return __traits(getMember, t, memberName);
     }

 ...
As simple as this: ``` string getTMember(T t, string memberName)() { return __traits(getMember, t, memberName); } ... writeln(getTMember!(t, "...")); ```
Noticed a mistake in my code ... ``` getTMember(T t, string memberName)() ``` Should be: ``` getTMember(T, string memberName)(T t) ``` And calling it should be like: ``` writeln(getTMember!("...")(t)); ```
May 30 2023
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 5/30/23 4:46 AM, John Xu wrote:
 How to put above enum as a function parameter? Following code wouldn't 
 work:
 
      string getTMember(T t, enum string memberName) {
          return __traits(getMember, t, memberName);
      }
compile time parameters come before runtime parameters: ```d string getTMember(string memberName)(T t) { return __traits(getMember, t, memberName); } // used like auto v = getTMember!"name"(t); ``` -Steve
May 30 2023
next sibling parent reply John Xu <728308756 qq.com> writes:
On Tuesday, 30 May 2023 at 15:43:12 UTC, Steven Schveighoffer 
wrote:
 On 5/30/23 4:46 AM, John Xu wrote:
 How to put above enum as a function parameter? Following code 
 wouldn't work:
 
      string getTMember(T t, enum string memberName) {
          return __traits(getMember, t, memberName);
      }
compile time parameters come before runtime parameters: ```d string getTMember(string memberName)(T t) { return __traits(getMember, t, memberName); } // used like auto v = getTMember!"name"(t); ``` -Steve
When render vibe.d diet template, string[] allMembers = __traits(allMembers, t); res.render!("index.dt", t, allMembers) if I don't want write memberName one by one in diet template: table - foreach(memberName; allMembers) tr Problem: memberName is not known at compile time.
May 30 2023
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 5/31/23 12:08 AM, John Xu wrote:

 
 When render vibe.d diet template,
 
      string[] allMembers = __traits(allMembers, t);
enum allMembers = __traits(allMembers, t);
      res.render!("index.dt", t, allMembers)
 
 if I don't want write memberName one by one in diet template:
 
      table
          - foreach(memberName; allMembers)
              tr


 
 Problem: memberName is not known at compile time.
The problem is that you stored the member name list as a runtime variable, and that is not known at compile time. Try the enum. Or really, just `foreach(memberName; __traits(allMembers, t))` right in the diet template. -Steve
Jun 01 2023
parent reply John Xu <728308756 qq.com> writes:
On Thursday, 1 June 2023 at 15:38:08 UTC, Steven Schveighoffer 
wrote:
 On 5/31/23 12:08 AM, John Xu wrote:

 
 When render vibe.d diet template,
 
      string[] allMembers = __traits(allMembers, t);
enum allMembers = __traits(allMembers, t);
      res.render!("index.dt", t, allMembers)
 
 if I don't want write memberName one by one in diet template:
 
      table
          - foreach(memberName; allMembers)
              tr


 
 Problem: memberName is not known at compile time.
The problem is that you stored the member name list as a runtime variable, and that is not known at compile time. Try the enum. Or really, just `foreach(memberName; __traits(allMembers, t))` right in the diet template. -Steve
Ok, thanks for all you gentlemen's help. I tried following function, now it works like C/C++/Python way: string getTMember(T t, string columnName) { foreach(member; __traits(allMembers, T)){ if (member == columnName) { return __traits(getMember, mcu, member).to!string; } } return ""; }
Jun 01 2023
next sibling parent John Xu <728308756 qq.com> writes:
A correction:

      string getTMember(T t, string columnName) {
          foreach(member; __traits(allMembers, T)){
              if (member == columnName) {
                  return __traits(getMember, t, member).to!string;
              }
          }
          return "";
      }
Jun 01 2023
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/1/23 10:58 PM, John Xu wrote:

 Ok, thanks for all you gentlemen's help. I tried following function,
 now it works like C/C++/Python way:
 
      string getTMember(T t, string columnName) {
          foreach(member; __traits(allMembers, T)){
              if (member == columnName) {
                  return __traits(getMember, mcu,
member).to!string;
              }
          }
          return "";
      }
 
You can use a switch, and the search for the right member name should be more optimized, though it's possible the compiler might recognize your pattern and do this anyway: ```d string getTMember(T t, string columnName) { switch(columnName) { static foreach(member; __traits(allMembers, T)) { case member: return __traits(getMember, t, member).to!string; } default: return ""; } } ``` This is a very common pattern in e.g. serialization libs in D. -Steve
Jun 02 2023
prev sibling parent bauss <jacobbauss gmail.com> writes:
On Tuesday, 30 May 2023 at 15:43:12 UTC, Steven Schveighoffer 
wrote:
 On 5/30/23 4:46 AM, John Xu wrote:
 How to put above enum as a function parameter? Following code 
 wouldn't work:
 
      string getTMember(T t, enum string memberName) {
          return __traits(getMember, t, memberName);
      }
compile time parameters come before runtime parameters: ```d string getTMember(string memberName)(T t) { return __traits(getMember, t, memberName); } // used like auto v = getTMember!"name"(t); ``` -Steve
Yeah I did fix it in my message right after
Jun 02 2023