Thread overview
Reflection to detect public/private/etc?
Aug 12, 2011
Nick Sabalausky
Aug 12, 2011
Adam D. Ruppe
Aug 12, 2011
Nick Sabalausky
Aug 12, 2011
Nick Sabalausky
Aug 12, 2011
Nick Sabalausky
Aug 12, 2011
Nick Sabalausky
August 12, 2011
Is there a way to check whether a class member (or other identifier) is public, private, protected, package or extern?

Or at least "public/extern" vs "private/protected/package"? (I suspect this one may at least be possible with some __traits(compiles, ...) trickery (assuming "private" actually works at this point), although I don't know whether it would have to take into accout the indentifier's type.)


August 12, 2011
There's no way I've found, aside from direct access (so not via getMembers) and seeing it it fails to compile.

I started hacking my compiler to add a traits(protection), but while I got it working on direct symbols, it didn't work on the stuff returned by __traits(getMember) so it didn't work for me... it looks like in the compiler, the protection is applied only to the name, not the stuff it points to.

I really want to get this figured out though so I can drop the leading underscore from some web.d names...
August 12, 2011
"Adam D. Ruppe" <destructionator@gmail.com> wrote in message news:j242up$24so$1@digitalmars.com...
>
> I really want to get this figured out though so I can drop the leading underscore from some web.d names...

Heh, that's exactly what I had in mind ;)


August 12, 2011
"Adam D. Ruppe" <destructionator@gmail.com> wrote in message news:j242up$24so$1@digitalmars.com...
> There's no way I've found, aside from direct access (so not via getMembers) and seeing it it fails to compile.
>

I just gave it a try. I think I may be hitting against a bug in __traits(compiles) WRT private. This is the best I could get (Using DMD 2.054, Win):

testCheckPrivate2.d:
-----------------------------
Foo foo;
class Foo
{
    int a;
    private int b;

    void c() {}
    private void d() {}

    void e(int x) {}
    private void f(int x) {}
}


testCheckPrivate.d:
-----------------------------
import testCheckPrivate2;

template check(string name)
{
    enum check = __traits(compiles, {
        auto x = &(__traits(getMember, foo, name));
    });
}

// Any way to do this with foreach? Didn't work when I tried.
template checkMembers(members...)
{
    static if(members.length > 0)
    {
        // Check the first
        pragma(msg,
            members[0] ~ ": " ~
            (check!(members[0]) ? "true" : "false")
        );

        // Check the rest
        static if(members.length > 1)
            alias checkMembers!(members[1..$]) dummy;
    }
}

alias checkMembers!(__traits(allMembers, Foo)) dummy;

pragma( msg, "Manually checking foo.d: " );
pragma( msg, __traits(compiles, { auto x = &(foo.d); }) );
void main()
{
    foo.d();
    auto x = &(foo.b);
    auto y = &(foo.d);
}

Result:
----------------
>dmd testCheckPrivate.d testCheckPrivate2.d -c
a: true
b: false
c: true
d: true
e: true
f: true
toString: true
toHash: true
opCmp: true
opEquals: false
Monitor: false
factory: true
Manually checking foo.d:
true
testCheckPrivate.d(33): Error: class testCheckPrivate2.Foo member d is not
accessible
testCheckPrivate.d(34): Error: class testCheckPrivate2.Foo member b is not
accessible

Note that "auto y = &(foo.d);" fails to compile as expected, but __traits(compiles) claims that should compile. It works for the non-function members though.

I did the "auto x = &(...);" trick so I wouldn't have to deal with the function's params. Maybe you know how to put dummy args in and make it an actual function call instead of taking the func's address? That's probably be a pain, but maybe it would get around the bug.


August 12, 2011
"Nick Sabalausky" <a@a.a> wrote in message news:j246df$2ael$1@digitalmars.com...
> "Adam D. Ruppe" <destructionator@gmail.com> wrote in message news:j242up$24so$1@digitalmars.com...
>> There's no way I've found, aside from direct access (so not via getMembers) and seeing it it fails to compile.
>>
>
> I just gave it a try. I think I may be hitting against a bug in __traits(compiles) WRT private. This is the best I could get (Using DMD 2.054, Win):
>
>
> Note that "auto y = &(foo.d);" fails to compile as expected, but __traits(compiles) claims that should compile. It works for the non-function members though.
>
> I did the "auto x = &(...);" trick so I wouldn't have to deal with the function's params. Maybe you know how to put dummy args in and make it an actual function call instead of taking the func's address? That's probably be a pain, but maybe it would get around the bug.
>

Oops, I misread the line number. The line "auto y = &(foo.d);" DOES compile. So it's not a bug in __traits(compiles). But it may simply be a bug in private. In other words: Taking the address of a private member function (from some other module) is currently allowed (but seems wrong to me). If that's fixed, then my code *should* work. But private has practically never worked anyway :(


August 12, 2011
Ok, this seems to work for member functions (it returns false for non-functions, but I think that's fixable by just detecting "function vs not function" and then using the appropriate __traits(compiles)).

enum check = __traits(compiles, {
    alias ParameterTypeTuple!(__traits(getMember, Foo, name)) T;
    T t;
    __traits(getMember, foo, name)( t );
 });

I have not tested it on fancy arguments like ref/in/out/lazy/etc., or on functions with a return value. But it seems to work on void(void) and void(int).

Here's the full relevent code:

template check(string name)
{
    enum check = __traits(compiles, {
        alias ParameterTypeTuple!(__traits(getMember, Foo, name)) T;
        T t;
        __traits(getMember, foo, name)( t );
    });
}

// Any way to do this with foreach? Didn't work when I tried.
template checkMembers(members...)
{
    static if(members.length > 0)
    {
        // Check the first
        pragma(msg,
            members[0] ~ ": " ~
            (check!(members[0]) ? "true" : "false")
        );

        // Check the rest
        static if(members.length > 1)
            alias checkMembers!(members[1..$]) dummy;
    }
}

alias checkMembers!(__traits(allMembers, Foo)) dummy;