digitalmars.D.learn - Reflection to detect public/private/etc?
- Nick Sabalausky (6/6) Aug 12 2011 Is there a way to check whether a class member (or other identifier) is
- Adam D. Ruppe (9/9) Aug 12 2011 There's no way I've found, aside from direct access (so not via
- Nick Sabalausky (3/5) Aug 12 2011 Heh, that's exactly what I had in mind ;)
- Nick Sabalausky (77/80) Aug 12 2011 I just gave it a try. I think I may be hitting against a bug in
- Nick Sabalausky (8/23) Aug 12 2011 Oops, I misread the line number. The line "auto y = &(foo.d);" DOES comp...
- Nick Sabalausky (36/36) Aug 12 2011 Ok, this seems to work for member functions (it returns false for
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.)
Aug 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...
Aug 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 ;)
Aug 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 -ca: 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.
Aug 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...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 :(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.
Aug 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;
Aug 12 2011