Thread overview
CT filtering of class members
Aug 11, 2019
Sjoerd Nijboer
Aug 11, 2019
Simen Kjærås
Aug 11, 2019
Sjoerd Nijboer
August 11, 2019
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()
    {
    }
}

August 11, 2019
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
August 11, 2019
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!