Build an AliasSeq from memberFunction return types
Simen Kjærås
simen.kjaras at gmail.com
Fri Mar 9 18:58:30 UTC 2018
On Friday, 9 March 2018 at 17:47:46 UTC, Timoses wrote:
> To retrieve the member names the following (and filtering for
> only the functions) does the job:
>
> alias members = aliasSeqOf!([__traits(allMembers, S)]);
This can be simplified to
alias members = Alias!(__traits(allMembers, S));
> However, I now would want to build an AliasSeq of the types. My
> idea would be (absolute pseudocode!!!):
>
> alias memberTypes;
> static foreach (member; members)
> {
> memberTypes ~= ReturnType!S.member;
> }
Generally, we use recursive templates in these cases:
template GetMemberTypes(funcs...) {
static if (funcs.length == 0) {
alias GetMemberTypes = AliasSeq!();
} else {
alias GetMemberTypes = AliasSeq!(
ReturnType!(funcs[0]),
GetMemberTypes!(funcs[1..$])
);
}
}
However, std.meta has staticMap, which will do this recursion for
us:
alias memberTypes = staticMap!(ReturnType, members);
Of course, this assumes 'members' contains only the functions you
care about. All in all, what you want can be boiled down to this
code:
import std.meta : staticMap, Alias, Filter;
import std.traits : isFunction, ReturnType;
import std.bitmanip : bitfields;
struct A
{
int a;
mixin(bitfields!(
uint, "x", 2,
int, "y", 3,
uint, "z", 2,
bool, "flag", 1));
}
template GetMember(T) {
alias GetMember(string name) = Alias!(__traits(getMember, T,
name));
}
alias memberTypes = staticMap!(ReturnType, Filter!(isFunction,
staticMap!(GetMember!A, __traits(allMembers, A))));
So, how does it work?
GetMember is a template that takes an aggregate type as a
parameter and returns a new template that takes a string. This
inner template then returns the member of the aggregate type that
has that name:
// Define a template that will find a member in A.
alias GetMemberOfA = GetMember!A;
// Get the 'flag' member of A.
alias someMemberOfA = GetMemberOfA!"flag";
Next: This line is a bit of a mouthful, so let's break it down:
alias memberTypes = staticMap!(ReturnType, Filter!(isFunction,
staticMap!(GetMember!A, __traits(allMembers, A))));
becomes:
// Grab the name of every single member of A.
alias allMemberNames = Alias!(__traits(allMembers, A));
// Define a template that will find a member in A.
alias GetMemberOfA = GetMember!A;
// Now get the members of A that correspond to the names
__traits(allMembers) returned.
alias allMembers = staticMap!(GetMemberOfA, allMemberNames);
// Get rid of everything that's not a function.
alias onlyFunctions = Filter!(isFunction, allMembers);
// And finally grab the return type of each function.
alias memberTypes = staticMap!(ReturnType, onlyFunctions);
--
Simen
More information about the Digitalmars-d-learn
mailing list