Thread overview
Traits: getting all *public* members of a class?
Jun 08, 2013
Q
Jun 08, 2013
Adam D. Ruppe
Jun 08, 2013
Andrej Mitrovic
Jun 08, 2013
Q
June 08, 2013
Hi there, I want to iterate over all the public members of a class, but I've hit a stumbling block when the class resides in a different module and also contains private members. For example:

$ cat foo.d
class Foo {
    private int x;
    public int y;
}

$ cat main.d
import foo;

void main() {
    foreach (mem; __traits(allMembers, Foo)) {
        enum prot = __traits(getProtection, __traits(getMember, Foo.init, mem));
        static if (prot == "public") {
            // ...
        }
    }
}

However, the compiler gives me the following error message:

$ dmd main foo
main.d(5): Error: class foo.Foo member x is not accessible

Since I'm not interested in the private members, is there any way to ignore them and only iterate over the public members? Or is reflection in this way disallowed when the target class lives in a different module?
June 08, 2013
You could probably throw in a traits(compiles) right above.

foreach(...) {
// or maybe compiles, getProtection(getMember))
static if(__traits(compiles, __traits(getMember,Foo.init, mem)) {
        enum prot = __traits(getProtection, __traits(getMember,
Foo.init, mem));
// and so on
}
}

I haven't actually tried this but generally static if(compiles) is a way to work around unwanted error messages.
June 08, 2013
On Saturday, 8 June 2013 at 13:57:13 UTC, Q wrote:
> Hi there, I want to iterate over all the public members of a class.

It is a known problem. The workaround is to use is(typeof()):

void main() {
    foreach (mem; __traits(allMembers, Foo))
    {
        static if (is(typeof(
            __traits(getMember, Foo.init, mem)
        )))
        {
            enum prot = __traits(getProtection,
                            __traits(getMember, Foo.init, mem));
            static if (prot == "public") {
                pragma(msg, mem);
            }
        }
    }
}
June 08, 2013
On Saturday, 8 June 2013 at 14:06:32 UTC, Andrej Mitrovic wrote:
> On Saturday, 8 June 2013 at 13:57:13 UTC, Q wrote:
>> Hi there, I want to iterate over all the public members of a class.
>
> It is a known problem. The workaround is to use is(typeof()):
>
> void main() {
>     foreach (mem; __traits(allMembers, Foo))
>     {
>         static if (is(typeof(
>             __traits(getMember, Foo.init, mem)
>         )))
>         {
>             enum prot = __traits(getProtection,
>                             __traits(getMember, Foo.init, mem));
>             static if (prot == "public") {
>                 pragma(msg, mem);
>             }
>         }
>     }
> }

This worked perfectly. Thank you!