I give up! I tried to create a reflection library but D's traits are just too screwed up!
Alex
AJ at gmail.com
Sat Apr 6 13:17:01 UTC 2019
On Friday, 5 April 2019 at 16:00:26 UTC, Adam D. Ruppe wrote:
> On Thursday, 4 April 2019 at 02:19:48 UTC, Alex wrote:
>> But because there is no `T` for fields we can't do it so easy,
>> so we have to construct the name and use string mixins.
>
> You should pass fields as an alias more often than not. It is a
> little tricky when you want to read/write it (the alias is not
> a value, so you need to pass a pointer or something
> separately), but for reflection you want to use the alias.
>
> UDAs do not exist on types per se, since they are tied to
> symbols.
>
>> mixin(`static foreach(a; __traits(getAttributes,
>> `~T.stringof~`.`~name~`))
>
> This shouldn't use mixin at all, and even if you do use mixin,
> it shouldn't be using stringof; .stringof is a code smell and
> should almost never be used. This bypasses the local symbol.
> That is actually the reason why you get a visibility error.
>
> Just use T. more info:
> https://stackoverflow.com/questions/32615733/struct-composition-with-mixin-and-templates/32621854#32621854
Ok, I was able to remove all of them I believe. I got in the
habit because I routinely switch the mixin to a pragma(msg and
having the actual name their is far more informative than T,
helps find out if the type if wrong).
I don't know why it is code smell, since it should ultimately end
up the same.
Fixing this did not solve the `private` error.
// Get the attributes for the field
mixin(`Protection = __traits(getProtection, T.`~name~`);`);
In any case, the code seems to be fundamentally working now, as I
mentioned in a previous thread. I just have to finish dealing
with all the other types, which shouldn't be a huge problem.
-----------
As far as using an alias as fields,
The code is this:
// Get the fields
alias n = FieldNameTuple!T;
static foreach(k, f; std.traits.Fields!T)
{{
Fields ~= (new cFieldReflection()).Reflect!(Alias!T, n[k]);
}}
I am passing the base type and the name then building it inside
Reflect, I've tried passing various things so I could simplify
the code, but I am unable to get anything to work.
auto Reflect(alias T, string name)()
{
static if (name != "")
{
// There is no field type so must manually construct and
duplicate code, else we could reflect directly
mixin(`import `~moduleName!T~`;`);
// mixin(`super.Reflect!(T.`~name~`);`);
Id = name;
static if (__traits(compiles, TypeName = T.stringof)) TypeName
= T.stringof~"."~name;
ModuleName = moduleName!(T);
FullName = fullyQualifiedName!(T)~"."~name;
MangledName = mangledName!T;
// Get the attributes for the field
mixin(`Protection = __traits(getProtection, T.`~name~`);`);
mixin(`static if (__traits(compiles, __traits(getProtection,
T.`~name~`)))
static foreach(a; __traits(getAttributes, T.`~name~`))
Attributes ~= sAttributeReflection(to!string(a),
typeof(a).stringof);`);
}
return this;
}
If I could call super.Reflect then it would fill in all the info
and I could remove the Id = name ... MangledName lines and
consolidate code. But I have not figure out how to get any of
that code to work without constructing the symbols by hand.
More information about the Digitalmars-d
mailing list