digitalmars.D.learn - Reflecting over mutating member functions
=?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
How do I iterate over all the `this`-mutating (non-`const` qualified) member functions of an aggregate (class/struct)?
Nov 09 2016
Jonathan M Davis via Digitalmars-d-learn writes:
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
Nov 09 2016