digitalmars.D.learn - loop through specific class members
- Trass3r (4/4) Jan 19 2009 Is there any way to loop through specific members of a class, e.g. all
- Daniel Keep (4/8) Jan 19 2009 Assuming you're using D2, http://digitalmars.com/d/2.0/traits.html might
- Trass3r (5/9) Jan 19 2009 It is indeed of interest though being not exactly what I want. Seems
- Lutger (2/13) Jan 19 2009 Indeed, perhaps it should be there. You could use getVirtualFunctions to...
- BCS (3/7) Jan 19 2009 you could define a template in another module that does the check and re...
- Trass3r (4/15) Jan 19 2009 Well, it'd indeed be used from a different module than class, in fact
- Daniel Keep (12/28) Jan 19 2009 It depends on what exactly you're trying to do. Some time ago, I wrote
- BCS (3/17) Jan 19 2009 you can get the names even in D1.0. Not exactly clean but...
- Daniel Keep (5/26) Jan 19 2009 I remember trying that, but abandoning it for some reason. This code is
- Trass3r (3/6) Jan 20 2009 Yeah but only works for structs. When used with classes returns an
- Trass3r (14/40) Jan 19 2009 What I want is a way that doesn't require much changes to the class
- Trass3r (5/5) Jan 20 2009 It seems like there is no way to automatically get the class methods in
- Jarrett Billingsley (3/7) Jan 20 2009 You're correct. __traits was introduced in D2 mostly because D1's
- Trass3r (11/19) Jan 20 2009 Yeah, __traits works quite well to get the function names, but I still
- Jarrett Billingsley (6/16) Jan 20 2009 Ah, that's what __traits(getMember) is for. You pass it an
- Trass3r (4/13) Jan 20 2009 OMG, I've already seen this function in the docs some time ago but
- Christopher Wright (17/25) Jan 20 2009 But unless you're doing very basic stuff or only touching a few classes,...
- Jarrett Billingsley (3/7) Jan 20 2009 Lol.
- Trass3r (6/19) Jan 21 2009 But why doesn't that work? It doesn't even work when forced to run at
- Sergey Gromov (7/27) Jan 25 2009 foreach() is a runtime construct. It may be *interpreted* at
- BCS (4/7) Jan 25 2009 OTOH a foreach on a tuple is a compile time construct, but it is a disti...
- Sergey Gromov (26/35) Jan 26 2009 I somehow missed that in the specs. Definitely, this works:
Is there any way to loop through specific members of a class, e.g. all public functions? I've already seen a function getMembers in druntime's ClassInfo class but I can't find anything related to the attributes there.
Jan 19 2009
Trass3r wrote:Is there any way to loop through specific members of a class, e.g. all public functions? I've already seen a function getMembers in druntime's ClassInfo class but I can't find anything related to the attributes there.Assuming you're using D2, http://digitalmars.com/d/2.0/traits.html might prove to be of interest. -- Daniel
Jan 19 2009
Daniel Keep schrieb:Assuming you're using D2, http://digitalmars.com/d/2.0/traits.html might prove to be of interest. -- DanielIt is indeed of interest though being not exactly what I want. Seems like there's currently no way to get attributes like public etc. But I think an acceptable workaround would be to use a common name prefix for specific methods and then use that allMembers trait.
Jan 19 2009
Trass3r wrote:Daniel Keep schrieb:Indeed, perhaps it should be there. You could use getVirtualFunctions to get all public+protected member functions that are not declared final, but that's not ideal. Another possible hack: if used from a different module, you could use the 'compiles' trait with allMembers to find out if a member can be accessed.Assuming you're using D2, http://digitalmars.com/d/2.0/traits.html might prove to be of interest. -- DanielIt is indeed of interest though being not exactly what I want. Seems like there's currently no way to get attributes like public etc. But I think an acceptable workaround would be to use a common name prefix for specific methods and then use that allMembers trait.
Jan 19 2009
Reply to Lutger,Another possible hack: if used from a different module, you could use the 'compiles' trait with allMembers to find out if a member can be accessed.you could define a template in another module that does the check and returns the result.
Jan 19 2009
BCS schrieb:Reply to Lutger,Well, it'd indeed be used from a different module than class, in fact from a different package. But this only gives the public members, right?Another possible hack: if used from a different module, you could use the 'compiles' trait with allMembers to find out if a member can be accessed.you could define a template in another module that does the check and returns the result.
Jan 19 2009
Trass3r wrote:BCS schrieb:It depends on what exactly you're trying to do. Some time ago, I wrote a library that created XML loaders for structs, and it needed to know the names of fields. Pre-traits, this is what I used: struct Stuff { int foo; char[] bar; alias Tuple!("foo", "bar") _fields; } Then I just looped over _fields. -- DanielReply to Lutger,Well, it'd indeed be used from a different module than class, in fact from a different package. But this only gives the public members, right?Another possible hack: if used from a different module, you could use the 'compiles' trait with allMembers to find out if a member can be accessed.you could define a template in another module that does the check and returns the result.
Jan 19 2009
Reply to Daniel,It depends on what exactly you're trying to do. Some time ago, I wrote a library that created XML loaders for structs, and it needed to know the names of fields. Pre-traits, this is what I used: struct Stuff { int foo; char[] bar; alias Tuple!("foo", "bar") _fields; } Then I just looped over _fields. -- Danielyou can get the names even in D1.0. Not exactly clean but... http://codepad.org/Eu16XqFu
Jan 19 2009
BCS wrote:Reply to Daniel,I remember trying that, but abandoning it for some reason. This code is getting old now; over two years now, so that might not have worked back then. -- DanielIt depends on what exactly you're trying to do. Some time ago, I wrote a library that created XML loaders for structs, and it needed to know the names of fields. Pre-traits, this is what I used: struct Stuff { int foo; char[] bar; alias Tuple!("foo", "bar") _fields; } Then I just looped over _fields. -- Danielyou can get the names even in D1.0. Not exactly clean but... http://codepad.org/Eu16XqFu
Jan 19 2009
BCS schrieb:you can get the names even in D1.0. Not exactly clean but... http://codepad.org/Eu16XqFuYeah but only works for structs. When used with classes returns an ExpressionTuple. Furthermore you only get the fields, I need the methods ;)
Jan 20 2009
Daniel Keep schrieb:What I want is a way that doesn't require much changes to the class itself but rather does the work in the module that actually uses the method names. What I'm trying to do is providing a mechanism for LuaLib to register a whole class automatically (and probably also checking all method's parameters for correctness). So far you have to register each method to be used in lua individually. So I was initially thinking about registering all protected methods or something like that. Guess I will use the prefix solution here cause it probably is the best way for this particular problem anyway. But yet I'm interested in (and also somewhat impressed by) the possibilities to do this ;) (reminds me of my search for a way to debug template and mixin stuff)It depends on what exactly you're trying to do. Some time ago, I wrote a library that created XML loaders for structs, and it needed to know the names of fields. Pre-traits, this is what I used: struct Stuff { int foo; char[] bar; alias Tuple!("foo", "bar") _fields; } Then I just looped over _fields.Well, it'd indeed be used from a different module than class, in fact from a different package. But this only gives the public members, right?Another possible hack: if used from a different module, you could use the 'compiles' trait with allMembers to find out if a member can be accessed.you could define a template in another module that does the check and returns the result.
Jan 19 2009
It seems like there is no way to automatically get the class methods in D1 currently?! __traits isn't supported, std.traits doesn't give anything usable, .tupleof only gets the fields (plus only giving an ExpressionTuple for classes).
Jan 20 2009
On Tue, Jan 20, 2009 at 10:29 AM, Trass3r <mrmocool gmx.de> wrote:It seems like there is no way to automatically get the class methods in D1 currently?! __traits isn't supported, std.traits doesn't give anything usable, .tupleof only gets the fields (plus only giving an ExpressionTuple for classes).You're correct. __traits was introduced in D2 mostly because D1's compile-time introspection is so paltry.
Jan 20 2009
Jarrett Billingsley schrieb:On Tue, Jan 20, 2009 at 10:29 AM, Trass3r <mrmocool gmx.de> wrote:Yeah, __traits works quite well to get the function names, but I still can't manage to get the corresponding function object to pass it to ParameterTypeTuple (for checking the parameters for correctness). Tried using ClassInfo's getMembers function but that apparently doesn't work. Base base = new Base; auto members = __traits(allMembers, typeof(base)); foreach(m; members) writefln(base.classinfo.getMembers(m).length); gives 0 for every member :(It seems like there is no way to automatically get the class methods in D1 currently?! __traits isn't supported, std.traits doesn't give anything usable, .tupleof only gets the fields (plus only giving an ExpressionTuple for classes).You're correct. __traits was introduced in D2 mostly because D1's compile-time introspection is so paltry.
Jan 20 2009
On Tue, Jan 20, 2009 at 2:13 PM, Trass3r <mrmocool gmx.de> wrote:Yeah, __traits works quite well to get the function names, but I still can't manage to get the corresponding function object to pass it to ParameterTypeTuple (for checking the parameters for correctness).Ah, that's what __traits(getMember) is for. You pass it an object/class and a string of the member name, and it gives you what it corresponds to.Tried using ClassInfo's getMembers function but that apparently doesn't work. Base base = new Base; auto members = __traits(allMembers, typeof(base)); foreach(m; members) writefln(base.classinfo.getMembers(m).length); gives 0 for every member :(I think that's actually a bug. DMD doesn't generate that info for some reason. I think LDC does.
Jan 20 2009
Jarrett Billingsley schrieb:On Tue, Jan 20, 2009 at 2:13 PM, Trass3r <mrmocool gmx.de> wrote:OMG, I've already seen this function in the docs some time ago but somehow I couldn't remember. Many thanks!Yeah, __traits works quite well to get the function names, but I still can't manage to get the corresponding function object to pass it to ParameterTypeTuple (for checking the parameters for correctness).Ah, that's what __traits(getMember) is for. You pass it an object/class and a string of the member name, and it gives you what it corresponds to.
Jan 20 2009
Jarrett Billingsley wrote:On Tue, Jan 20, 2009 at 10:29 AM, Trass3r <mrmocool gmx.de> wrote:But unless you're doing very basic stuff or only touching a few classes, compile-time introspection ends up being quite costly. I want runtime reflection for that reason. On the other hand, you can get the non-final, non-private methods of a class with something like: foreach (member; __traits (allMembers, Class)) { foreach (overload; __traits (getVirtualFunctions, Class, member)) { // do stuff } } Naturally, __traits and foreach don't mix, so you'll have to use template recursion. This is pretty damn ugly. Note that getVirtualFunctions returns methods that are not virtual. You need to use isVirtualFunction to determine whether a method is virtual.It seems like there is no way to automatically get the class methods in D1 currently?! __traits isn't supported, std.traits doesn't give anything usable, .tupleof only gets the fields (plus only giving an ExpressionTuple for classes).You're correct. __traits was introduced in D2 mostly because D1's compile-time introspection is so paltry.
Jan 20 2009
On Tue, Jan 20, 2009 at 7:42 PM, Christopher Wright <dhasenan gmail.com> wrote:Naturally, __traits and foreach don't mix, so you'll have to use template recursion. This is pretty damn ugly.I never understood why __traits likes returning arrays so much. Why not tuples?Note that getVirtualFunctions returns methods that are not virtual. You need to use isVirtualFunction to determine whether a method is virtual.Lol.
Jan 20 2009
Christopher Wright schrieb:On the other hand, you can get the non-final, non-private methods of a class with something like: foreach (member; __traits (allMembers, Class)) { foreach (overload; __traits (getVirtualFunctions, Class, member)) { // do stuff } } Naturally, __traits and foreach don't mix, so you'll have to use template recursion. This is pretty damn ugly.But why doesn't that work? It doesn't even work when forced to run at compile time by CTFE. Had a look at the compiler code, it uses the same mechanism as pragma(msg, for example, so shouldn't something like the above theoretically be possible?
Jan 21 2009
Wed, 21 Jan 2009 12:48:07 +0100, Trass3r wrote:Christopher Wright schrieb:foreach() is a runtime construct. It may be *interpreted* at compile-time, but it's interpreted as if it were run time nevertheless. It dynamically changes the value of 'member' variable. pragma() and __traits() are compile-time constructs. They are fully and statically expanded before anything is being interpreted and cannot handle dynamically changing variables.On the other hand, you can get the non-final, non-private methods of a class with something like: foreach (member; __traits (allMembers, Class)) { foreach (overload; __traits (getVirtualFunctions, Class, member)) { // do stuff } } Naturally, __traits and foreach don't mix, so you'll have to use template recursion. This is pretty damn ugly.But why doesn't that work? It doesn't even work when forced to run at compile time by CTFE. Had a look at the compiler code, it uses the same mechanism as pragma(msg, for example, so shouldn't something like the above theoretically be possible?
Jan 25 2009
Hello Sergey,foreach() is a runtime construct. It may be *interpreted* at compile-time, but it's interpreted as if it were run time nevertheless. It dynamically changes the value of 'member' variable.OTOH a foreach on a tuple is a compile time construct, but it is a distinct construct from the array foreach and is not what you are using (If i'm reading stuff correctly)
Jan 25 2009
Mon, 26 Jan 2009 04:50:10 +0000 (UTC), BCS wrote:Hello Sergey,I somehow missed that in the specs. Definitely, this works: template Tuple(T...) { alias T Tuple; } void foo() { foreach (a; Tuple!(int, char, long)) pragma(msg, a.stringof); } but this doesn't: template Tuple(T...) { alias T Tuple; } void foo() { foreach (a; Tuple!("a", "b", "c")) pragma(msg, a); } $ dmd -c test.d test.d(8): Error: string expected for message, not 'a' test.d(8): Error: string expected for message, not 'a' test.d(8): Error: string expected for message, not 'a' *This* seems like a bug to me.foreach() is a runtime construct. It may be *interpreted* at compile-time, but it's interpreted as if it were run time nevertheless. It dynamically changes the value of 'member' variable.OTOH a foreach on a tuple is a compile time construct, but it is a distinct construct from the array foreach and is not what you are using (If i'm reading stuff correctly)
Jan 26 2009
Hello Sergey,but this doesn't: template Tuple(T...) { alias T Tuple; } void foo() { foreach (a; Tuple!("a", "b", "c")) pragma(msg, a); } $ dmd -c test.d test.d(8): Error: string expected for message, not 'a' test.d(8): Error: string expected for message, not 'a' test.d(8): Error: string expected for message, not 'a' *This* seems like a bug to me.try indexing it: template Tuple(T...) { alias T Tuple; } void foo() { alias Tuple!("a", "b", "c") Tpl; foreach (i,a; Tpl) pragma(msg, Tpl[i]); } (BTW that is a known bug)
Jan 26 2009
BCS schrieb:Hello Sergey,Do you know the bug number?but this doesn't: template Tuple(T...) { alias T Tuple; } void foo() { foreach (a; Tuple!("a", "b", "c")) pragma(msg, a); } $ dmd -c test.d test.d(8): Error: string expected for message, not 'a' test.d(8): Error: string expected for message, not 'a' test.d(8): Error: string expected for message, not 'a' *This* seems like a bug to me.try indexing it: template Tuple(T...) { alias T Tuple; } void foo() { alias Tuple!("a", "b", "c") Tpl; foreach (i,a; Tpl) pragma(msg, Tpl[i]); } (BTW that is a known bug)
Mar 29 2009