www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - CT filtering of class members

reply Sjoerd Nijboer <dlang sjoerdnijboer.com> writes:
The following snippet doesn't compile

I am trying to reflect on a class and only do an operation with 
all member functions of a class.
But I can't seem to use a filter to only get the member functions 
out of a type T.

I understand that there are two errors in my snippet.
1) It cannot mixin a `name` because it is a variable from the 
lambda that `filter()` is using.
2) members.filter!(name => !ctorAndDtor.canFind(name)) does not 
filter on symbols defined in ctorAndDtor

How can I fix these problems and return all member functions 
whitout ctor and dtor of a type T?

Code snippet:

void main()
{
     GetFunctionMembers!Foo();
}

void GetFunctionMembers(T)()
{
     enum members = [__traits(derivedMembers, T)];
     pragma(msg, "Functions: " ~ members.stringof);

     enum ctorAndDtor = ["this", "__ctor", "__dtor"];
     enum memberFunctions = members.filter!(name => 
!ctorAndDtor.canFind(name)
                 && mixin("isFunction!(T." ~ name ~ ")"))();

     pragma(msg, memberFunctions);
}

class Foo
{
     bool myBool;
     int k;

     this()
     {
     }

     ~this()
     {
     }

     void bar(int k)
     {
         this.k = k;
     }

     void qux()
     {
     }
}
Aug 11 2019
parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Sunday, 11 August 2019 at 15:27:54 UTC, Sjoerd Nijboer wrote:
 The following snippet doesn't compile

 I am trying to reflect on a class and only do an operation with 
 all member functions of a class.
 But I can't seem to use a filter to only get the member 
 functions out of a type T.

 I understand that there are two errors in my snippet.
 1) It cannot mixin a `name` because it is a variable from the 
 lambda that `filter()` is using.
 2) members.filter!(name => !ctorAndDtor.canFind(name)) does not 
 filter on symbols defined in ctorAndDtor

 How can I fix these problems and return all member functions 
 whitout ctor and dtor of a type T?
This is classic D mix of compile-time and compile-time (no typo). I suggest reading H.S. Teoh's text on the topic: https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time Now, as for what can actually be done: you should probably use std.meta.Filter (https://dlang.org/library/std/meta/filter.html) to filter the members list. This will require you to define a template to operate on each element. Something like this: import std.meta : Filter; import std.traits : isFunction; import std.algorithm.searching : canFind; enum isNonspecialMemberFunction(string name) = !ctorAndDtor.canFind(name) && isFunction!(__traits(getMember, T, name)); enum memberFunctions = Filter!(isNonspecialMemberFunction, __traits(derivedMembers, T)); Filter operates on AliasSeqs, not arrays. That's why I restated the __traits(derivedMembers, T) part, but this could just as easily be done by changing this line: enum members = [__traits(derivedMembers, T)]; to: alias members = __traits(derivedMembers, T); -- Simen
Aug 11 2019
parent Sjoerd Nijboer <dlang sjoerdnijboer.com> writes:
On Sunday, 11 August 2019 at 16:32:20 UTC, Simen Kjærås wrote:
 [...] Something like this:

     import std.meta : Filter;
     import std.traits : isFunction;
     import std.algorithm.searching : canFind;

     enum isNonspecialMemberFunction(string name) = 
 !ctorAndDtor.canFind(name) &&
                                        
 isFunction!(__traits(getMember, T, name));
     enum memberFunctions = Filter!(isNonspecialMemberFunction, 
 __traits(derivedMembers, T));

 Filter operates on AliasSeqs, not arrays. That's why I restated 
 the __traits(derivedMembers, T) part, but this could just as 
 easily be done by changing this line:

     enum members = [__traits(derivedMembers, T)];

 to:

     alias members = __traits(derivedMembers, T);

 --
   Simen
Works beautiful, thank you very much!
Aug 11 2019