Getting a tuple of all members of a struct or a class
Philippe Sigaud
philippe.sigaud at gmail.com
Sun Jul 11 07:03:07 PDT 2010
Damn, sorry for the botched post. One tab too many.
So, I'm trying to get a feel for __traits(allMembers, T). I'm using it to get
a tuple consisting of the types and names of a type.
Let say I have
struct S
{
int i;
double delegate(double) d;
int foo(int j) { return i*j;}
}
I want Members!S to be:
TypeTuple!(int, "i", double delegate(double), "d", int function(int), "foo")
I'm almost there, but I have some troubles:
- first, if foo is defined many times inside S, I get it only once. Is there
any way to get overloaded function inside a struct? (for a class, I'll have a
look at __traits(getOverloads, T)).
- second, classes have a Monitor member that's wreaking havoc with my code.
Any help on this would be welcome. Maybe I'll just jump over it.
- third, DMD is a bit incoherent when it comes to tuples and strings thereof
(hi, retard!). For example, all my types are wrapped in parenthesis like this:
((int), "i", (double delegate(double)), "d", ...)
- also, methods are treated differently than member functions. In the above
example, foo gives me 'int function(int j)' as a type and not 'int
function(int)'. It's cumbersome.
Annex: the code:
/**
Double-decker template to get the type of T.member. It's a 2 stage template to
be used by staticMap
*/
template GetMember(T)
{
template GetMember(string member)
{
mixin(getMember!T(member));
}
}
/**
Helper CT string generator function.
*/
string getMember(T)(string member)
{
return
"static if (is( typeof(&(T." ~ member ~ ") ) ) )
alias typeof(&T." ~ member ~ ") GetMember;
else
alias typeof(T." ~ member ~ ") GetMember;";
}
/**
Given a type T, returns a typetuple of all members of a class or a struct,
alternating
with their names: TypeTuple!(int, "a", double function(string), "fun").
*/
template Members(T) if (is (T == class) || is (T == struct))
{
alias Interleave!(staticMap!(GetMember!T, __traits(allMembers, T)),
__traits(allMembers, T)) Members;
}
/**
Helper template. Given T0, T1, T2, ..., Tn, Tn+1, ... T2n, will returns
the interleaving of the first part with the second part: T0, Tn+1, T1, Tn+2,
... Tn, T2n
It's fragile: no test, etc. A better way to do this would be as a two-steps
template: Interleave!(T...).With!(U...)
*/
template Interleave(T...)
{
static if (T.length > 1)
alias TypeTuple!(T[0], T[$/2], Interleave!(T[1..$/2], T[$/2+1 .. $]))
Interleave;
else
alias T Interleave;
}
void main() {
alias object.AssociativeArray!(int,double) T;
// alias Test T;
alias Members!T M;
writeln(M.stringof);
}
More information about the Digitalmars-d
mailing list