March 12, 2014
Hi all,

First time I'm posting here, so if this isn't the right place to ask such questions, feel free to redirect me.

I wish to know (in compile time, of course) if any member of a struct has a certain UDA. If any member has it, it implies "propagates" to the struct as a whole. I wrote this code, which works:

template hasAttributeByName(ATTR, STRUCT) {
    template byName(string NAME) {
        enum byName = staticIndexOf!(ATTR, __traits(getAttributes, __traits(getMember, STRUCT, NAME))) != -1;
    }
}
template anyMemberHasAttribute(ATTR, STRUCT) {
    alias pred = hasAttributeByName!(ATTR, STRUCT);
    enum anyMemberHasAttribute = anySatisfy!(pred.byName, __traits(allMembers, STRUCT));
}

enum MyUDA;
struct MyStruct {
    int a;
    @MyUDA int b;
}
pragma(msg, anyMemberHasAttribute!(MyUDA, MyStruct));


This works and prints `true`. I then tried to make this code a little more generic, but for some reason I can't get it working:


template anyMemberSatisfies(alias PRED, STRUCT) {
    template byName(string NAME) {
        enum byName = PRED!(__traits(getMember, STRUCT, NAME));
    }

    enum anyMemberSatisfies = anySatisfy!(byName, __traits(allMembers, STRUCT));
}
template hasAttribute(alias ATTR) {
    template pred(alias VAR) {
        enum pred = staticIndexOf!(ATTR, __traits(getAttributes, VAR)) != -1;
    }
}

alias hasMyUDA = hasAttribute!MyUDA;

// fails to compile
pragma(msg, anyMemberSatisfies!(hasMyUDA.pred, MyStruct));


The error I'm getting is

(219): Error: template instance PRED!(a) cannot use local 'a' as parameter to non-global template pred(alias VAR)
typetuple.d(632): Error: template instance serialization.anyMemberSatisfies!(pred, MyStruct).F!"a" error instantiating
(222):        instantiated from here: anySatisfy!(byName, "a")
(238):        instantiated from here: anyMemberSatisfies!(pred, MyStruct)
(222): Error: template instance std.typetuple.anySatisfy!(byName, "a") error instantiating
(238):        instantiated from here: anyMemberSatisfies!(pred, MyStruct)
(238): Error: template instance serialization.anyMemberSatisfies!(pred, MyStruct) error instantiating
(238):        while evaluating pragma(msg, anyMemberSatisfies!(pred, MyStruct))


I get such an error for each member of the struct.
By the way, I tried using ``mixin(STRUCT.stringof ~ ".init." ~ NAME)`` instead of ``__traits(getMember, STRUCT, NAME)`` but to no avail.

What am I doing wrong?

Thanks in advance,
-Tomer