Thread overview
Finding UDAs with Templates
Jul 23, 2013
Paul O'Neil
Jul 23, 2013
Jacob Carlborg
Jul 23, 2013
Artur Skawina
Jul 23, 2013
Jacob Carlborg
Jul 24, 2013
Paul O'Neil
July 23, 2013
I'm trying to write some code that finds all the members of a class that have a particular user defined attribute.  My current attempt is at https://github.com/todayman/d_template_experiments/tree/8fccd27d7d5557ec6e2f0614374cf5f79fe80b4c

I would like to have a static method that returns an array of strings of the names of the members with the "@Sync" attribute.  I use the allMembers trait to get the list of strings, then try to filter out the ones I want.  There are problems when I convert from the string to a symbol / something to get the attributes.  Right now, I'm getting errors like:


> metadata.d(158): Error: template instance doesFieldSync_imp!(_hash) cannot use local '_hash' as parameter to non-global template doesFieldSync_imp(alias field)()

which I understand is related to
http://d.puremagic.com/issues/show_bug.cgi?id=5710

and

> metadata.d(160): Error: first argument is not a symbol
from
_traits(getAttributes, mxin("FileData."~key))

What's a good way to work around these?  I'm also open to entirely different ways of doing this.

Thanks,
Paul
July 23, 2013
On 2013-07-23 06:27, Paul O'Neil wrote:
> I'm trying to write some code that finds all the members of a class that
> have a particular user defined attribute.  My current attempt is at
> https://github.com/todayman/d_template_experiments/tree/8fccd27d7d5557ec6e2f0614374cf5f79fe80b4c
>
>
> I would like to have a static method that returns an array of strings of
> the names of the members with the "@Sync" attribute.  I use the
> allMembers trait to get the list of strings, then try to filter out the
> ones I want.  There are problems when I convert from the string to a
> symbol / something to get the attributes.  Right now, I'm getting errors
> like:

I tried your code and this should be enough:

import std.typetuple;

static bool doesFieldSync (string field) ()
{
    alias attrs = TypeTuple!(__traits(getAttributes, mixin("FileData." ~ field)));
    return staticIndexOf!(Sync, attrs) != -1;
}

The important things here are that __traits(getAttributes) returns a tuple. You cannot assign a tuple to a variable. But you can alias it. When you alias it you do need to use this wrapper TypeTuple, I don't remember why but that's how it works.

// This is the method I'm trying to write
static string[] syncableFields() {
    auto result = new string[0];
    foreach( key ; __traits(derivedMembers, FileData) )
    {
        if( doesFieldSync!key() ) {
            result ~= key;
        }
    }
    return result;
}

Here I used derivedMembers instead of allMembers, this is want you want, most times.

But I see that there are some problems with some members. These members are mixed in "mixin Signal". So if you try to filter out these members. I would just hard code them.

-- 
/Jacob Carlborg
July 23, 2013
On 07/23/13 08:38, Jacob Carlborg wrote:
> static bool doesFieldSync (string field) ()
> {
>     alias attrs = TypeTuple!(__traits(getAttributes, mixin("FileData." ~ field)));
>     return staticIndexOf!(Sync, attrs) != -1;
> }
> 
> The important things here are that __traits(getAttributes) returns a tuple. You cannot assign a tuple to a variable.

We can. :)

   enum attrs = __traits... // `auto` would work too.

Just be careful and remember the `typeof(attrs)` part if/when
using staticIndexOf with types - it might otherwise return bogus
results (instead of failing).

   staticIndexOf!(Sync, typeof(attrs))

artur
July 23, 2013
On 2013-07-23 12:59, Artur Skawina wrote:

> We can. :)
>
>     enum attrs = __traits... // `auto` would work too.

I can't remember that working for me, but perhaps it does.

> Just be careful and remember the `typeof(attrs)` part if/when
> using staticIndexOf with types - it might otherwise return bogus
> results (instead of failing).
>
>     staticIndexOf!(Sync, typeof(attrs))

Yeah, I think I encountered something like that.

-- 
/Jacob Carlborg
July 24, 2013
I basically ended up doing what Jacob suggested.

To deal with the extra members from "mixin Signal" by using the compiles trait to avoid the normal case for them.

Thanks for the help.
Paul