Thread overview | |||||
---|---|---|---|---|---|
|
January 25, 2018 Using std traits | ||||
---|---|---|---|---|
| ||||
I decided it's time to learn how std traits work. I still find the whole compile time business a bit weird to deal with, so I decided to write a simple JSON serializer for struct that loops over member fields and outputs them. import std.stdio; import std.json; import std.traits; struct TestStruct { @("noserialize") int x; int y; int z; } void serialize(T)(T obj) { if (is(T == struct)) { foreach (i, member; FieldNameTuple!T) { if (!hasUDA!(member, "noserialize")) { writeln(member); } } } else { assert(0, "Not a struct"); } } void main() { TestStruct ts; ts.x = 1; ts.y = 2; ts.z = 3; serialize(ts); } here's a runnable version: https://ideone.com/U4ROAT I expected it to output "y" "z", but "x" is also present. What am I doing wrong with hasUDA? |
January 25, 2018 Re: Using std traits | ||||
---|---|---|---|---|
| ||||
Posted in reply to JN | On 01/25/2018 11:49 AM, JN wrote:
> foreach (i, member; FieldNameTuple!T)
> {
> if (!hasUDA!(member, "noserialize"))
> {
> writeln(member);
> }
'member' is a string local variable, which does not have that UDA. You need to get the symbol of the struct:
if (!hasUDA!(__traits(getMember, T, member), "noserialize"))
{
writeln(member);
}
However, note that you're using a compile-time foreach, which expands its body for each iteration. Since you used a regular if, you have three checks at runtime.
What you really want is use a 'static if':
static if (!hasUDA!(__traits(getMember, T, member), "noserialize"))
{
writeln(member);
}
Aaah... Much lighter... :)
Even further, you may want to consider using a 'static foreach':
static foreach (i, member; FieldNameTuple!T)
{
// ...
}
That is more powerful because it can iterate over more ranges. However there are some differences from the regular foreach: For example, 'static foreach' does not introduce a scope per iteration.
Ali
|
January 25, 2018 Re: Using std traits | ||||
---|---|---|---|---|
| ||||
Posted in reply to JN | On Thursday, 25 January 2018 at 19:49:05 UTC, JN wrote:
> if (!hasUDA!(member, "noserialize"))
Nevermind, I get it now, member is only the field name, not a 'reference', changed it to:
if (!hasUDA!(mixin(T.stringof ~ "." ~ member), "noserialize"))
and works now
|
Copyright © 1999-2021 by the D Language Foundation