www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using traits get a list of methods and filter out the member vars.

reply "Gary Willoughby" <dev nomad.so> writes:
When iterating through class members using traits how do you 
filter out the member vars to only get a list of methods. I think 
i've solved it in the code below but it feels like i am abusing 
MemberFunctionsTuple. Is this the correct way to do this?

private template Methods(T, int index = 0)
{
	private string getMethods()
	{
		string code = "";
		static if (index < __traits(allMembers, T).length)
		{
			static if (MemberFunctionsTuple!(T, __traits(allMembers, 
T)[index]).length)
			{
				code ~= __traits(allMembers, T)[index] ~ "\n";
			}
			code ~= Methods!(T, index + 1);
		}
		return code;
	}
	enum Methods = getMethods();
}
Sep 08 2013
parent reply "Dicebot" <public dicebot.lv> writes:
http://dpaste.dzfl.pl/c250e798

import std.traits, std.range;

private template Methods(T)
	if (is(T == class))
{
	private string[] getMethods()
	{
		string result[];
		
		foreach (member_string; __traits(allMembers, T))
		{
			mixin("alias member = " ~ T.stringof ~ "." ~ member_string ~ 
";");
			static if (is(typeof(member) == function))
			{

				result ~= __traits(identifier, member);
			}
		}	
		return result;
	}
	
	enum Methods = getMethods().join("\n");
}

class A
{
	int a;
	void delegate() dg;
	void foo() { }
}

void main()
{
	pragma(msg, Methods!A);
}
Sep 08 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
Key part here is "is(T == function)" - because of D type system 
funny properties only possible way to get T that matches that 
condition is to do `typeof` from declared function/method symbol. 
That type can't be manually expressed and thus used for member 
variable.
Sep 08 2013
prev sibling parent reply "Gary Willoughby" <dev nomad.so> writes:
On Sunday, 8 September 2013 at 13:46:26 UTC, Dicebot wrote:
 http://dpaste.dzfl.pl/c250e798

 import std.traits, std.range;

 private template Methods(T)
 	if (is(T == class))
 {
 	private string[] getMethods()
 	{
 		string result[];
 		
 		foreach (member_string; __traits(allMembers, T))
 		{
 			mixin("alias member = " ~ T.stringof ~ "." ~ member_string ~ 
 ";");
 			static if (is(typeof(member) == function))
 			{

 				result ~= __traits(identifier, member);
 			}
 		}	
 		return result;
 	}
 	
 	enum Methods = getMethods().join("\n");
 }

 class A
 {
 	int a;
 	void delegate() dg;
 	void foo() { }
 }

 void main()
 {
 	pragma(msg, Methods!A);
 }
This looks like a nice solution but i get errors when used across modules. The problem is that allmembers emits private members so across modules they are not available.
Sep 08 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Sunday, 8 September 2013 at 16:43:16 UTC, Gary Willoughby 
wrote:
 This looks like a nice solution but i get errors when used 
 across modules. The problem is that allmembers emits private 
 members so across modules they are not available.
You want to list private members or want them ignored with no errors?
Sep 08 2013
parent reply "Gary Willoughby" <dev nomad.so> writes:
On Sunday, 8 September 2013 at 17:07:57 UTC, Dicebot wrote:
 On Sunday, 8 September 2013 at 16:43:16 UTC, Gary Willoughby 
 wrote:
 This looks like a nice solution but i get errors when used 
 across modules. The problem is that allmembers emits private 
 members so across modules they are not available.
You want to list private members or want them ignored with no errors?
Just ignored with no errors.
Sep 08 2013
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
Something along the lines of

static if(__traits(compiles, __traits(getMember, Foo, member))
    static if(is(__traits(getMember, Foo, member) == function)) {
      // use it
    }


The __traits(compiles, ...) is my go-to thingy for filtering out 
random errors.
Sep 08 2013
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2013-09-08 18:43, Gary Willoughby wrote:

 This looks like a nice solution but i get errors when used across
 modules. The problem is that allmembers emits private members so across
 modules they are not available.
I'm wondering if it tries to call the method here: static if (is(typeof(member) == function)) Since D allows to call methods without parentheses. -- /Jacob Carlborg
Sep 08 2013
parent "Dicebot" <public dicebot.lv> writes:
On Sunday, 8 September 2013 at 19:48:31 UTC, Jacob Carlborg wrote:
 I'm wondering if it tries to call the method here:

 static if (is(typeof(member) == function))

 Since D allows to call methods without parentheses.
No, not in typeof. It will try to call it with `member.stringof` though, thus for functions usage of __traits(identifier) is necessary.
Sep 08 2013