www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to get only the field name from an alias?

reply Elfstone <elfstone yeah.net> writes:
I'm experimenting on a serializer design. The idea includes a 
shorthand for processing a field and its attributes with an 
alias. But I'm not sure whether I can gather enough information 
from it, such as the name of the field. apparently F.stringof 
stands for "this.\<fieldname\>" in this context. So how can I get 
only the field's name? And is it possible to check if F is a 
field? -- In a well defined manner.

	import std.stdio;

	void processField(alias F)(Serializer sz) // is field?
	{
		writeln("attrs ", __traits(getAttributes, F)); // OK
		writeln(F.stringof); // "this.intField"
		sz.process(F.stringof, F); // "serializing int this.intField: 0"
	}

	class Serializer
	{

		void process(string k, ref int v)
		{
			writeln("serializing int ", k, ": ", v);
		}

		void process(string k, ref long v)
		{
			writeln("serializing long ", k, ": ", v);
		}

		void process(U)(ref U v) if (is(U == struct))
		{
			v.serialize(this);
		}
	}

	struct OldName
	{
		string name;
	}

	struct Serializable
	{
		 OldName("ifield")
		int intField;

		void serialize(Serializer sz)
		{
			sz.processField!intField();
		}
	}

	void main()
	{
		import std.stdio;
		import std.traits;
		import core.internal.traits;

		Serializable v;
		auto sz = new Serializer();
		sz.process(v);
	}
Feb 20 2023
next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
I'm not sure what the solution is for your specific question, but 
there is some alternative way you could do: (no longer need 
function on your struct)

I tried to comment the lines, even thought i'm not sure i 
remember everything correctly, but it compiles :p

More info: https://dlang.org/spec/traits.html

```D
import std.stdio;

class Serializer
{
     void process(string k, ref int v)
     {
         writeln("serializing int ", k, ": ", v);
     }

     void process(string k, ref long v)
     {
         writeln("serializing long ", k, ": ", v);
     }

     void process(U)(ref U v) if (is(U == struct))
     {
         // get all members from U
         static foreach (member; __traits(allMembers, U))
         {
             // get attributes from U.member
             static foreach (attr; __traits(getAttributes, 
__traits(getMember, U, member)))
             {
                 // is the attribute OldName
                 static if (is(typeof(attr) == OldName))
                 {
                     // the name you put in OldName attribute
                     string oldName = attr.name;
                     auto value = __traits(getMember, v, member);

                     writeln("field: ", member);
                     writeln("oldname: ", oldName);
                     writeln("value: ", value);
                 }
             }
         }
     }
}

struct OldName
{
     string name;
}

struct Serializable
{
      OldName("ifield")
     int intField;
}

void main()
{
     import std.stdio;
     import std.traits;
     import core.internal.traits;

     Serializable v;
     auto sz = new Serializer();
     sz.process(v);
}
```
Feb 20 2023
parent Elfstone <elfstone yeah.net> writes:
On Tuesday, 21 February 2023 at 03:13:38 UTC, ryuukk_ wrote:
 I'm not sure what the solution is for your specific question, 
 but there is some alternative way you could do: (no longer need 
 function on your struct)

 [...]
This is super neat, but the order of the fields will have to be frozen, and I won't be able to do something like this: sz.processField!hasData(); if (this.hasData) { sz.processField!data(); } Unless I can mark versions and dependencies with attributes and analyse them somehow. The Deserializer shares the same interface by the way.
Feb 20 2023
prev sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Tuesday, 21 February 2023 at 02:41:34 UTC, Elfstone wrote:
 apparently F.stringof
You almost never want to use .stringof, instead try __traits(identifier, F) and see what it gives you. Alternatively, loop over __traits(allMembers) which gives you the member names and pass that down. You can pull all the info out of allMembers with getMember and then other things to filter it out.
Feb 21 2023
parent Elfstone <elfstone yeah.net> writes:
On Tuesday, 21 February 2023 at 12:32:51 UTC, Adam D Ruppe wrote:
 On Tuesday, 21 February 2023 at 02:41:34 UTC, Elfstone wrote:
 apparently F.stringof
You almost never want to use .stringof, instead try __traits(identifier, F) and see what it gives you. Alternatively, loop over __traits(allMembers) which gives you the member names and pass that down. You can pull all the info out of allMembers with getMember and then other things to filter it out.
Thanks, Adam! Didn't know such a trait existed and that it could work for aliases.
Feb 22 2023