Reflecting over mutating member functions

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Nov 9 05:21:10 PST 2016


On Wednesday, November 09, 2016 12:21:19 Nordlöw via Digitalmars-d-learn 
wrote:
> How do I iterate over all the `this`-mutating (non-`const`
> qualified) member functions of an aggregate (class/struct)?

__traits(allMembers, T) can be used to get a Tuple/AliasSeq of strings of
the names of all of the members of T. Then for each of them,
__traits(getOverloads, T, memberName) can be used be used to get a
Tuple/AliasSeq of the overloads for that member (its length will be 0 if the
member is not a function). You'll probably want to ignore anything starting
with __, otherwise you'd get stuff like the constructor, destructor,
postblit constructor, etc. You can use __traits(isStaticFunction, ...) on
the overloads to strip out the static functions, and you can use
std.traits.functionAttributes to check whether the function has
FunctionAttribute.const_ and strip out those that do. I could be missing
something, but I think that that gets you there. If not, it's at least
close. Regardless, for this sort of thing, you typically have to use some
combination of __traits, is expressions, and std.traits.

http://dlang.org/spec/traits.html

The key thing to getting started is to use __traits(allMembers, ...) to get
the list of members and then either __traits(getOverloads, ...) or
__traits(getMember, ...) to get the symbols for those members (the downside
of getMember being that it just grabs the first one that matches, but that's
really just a problem for functions, and getOverloads can be used for them).
In general though, you should really unit test this sort of code thoroughly
in order to catch the corner cases. For instance, to create a trait that
checks whether a member is static or not is suprisingly difficult (__traits
only will tell you about static member functions, not variables), and the
solutions that several of us were using did not fit all of the test cases
that Manu came up with when trying to solve the problem. Without a thorough
set of tests, it was easy to miss that.

https://github.com/dlang/phobos/pull/4834

Another thing to keep in mind is that for some stupid reason, you can't
alias the result of __traits, but you _can_ use std.meta.AliasSeq or
std.meta.Alias to wrap them. e.g.

alias members = __traits(allMembers, T);

won't work, but

alias members = AliasSeq!(__traits(allMembers, T));

will. There's an open bug report for it somewhere, but until it's fixed,
you're stuck with the extra Alias or AliasSeq.

- Jonathan M Davis




More information about the Digitalmars-d-learn mailing list