www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Getting a tuple of all members of a struct or a class

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)

Helper CT string generator function.
string getMember(T)(string member)
       "static if (is( typeof(&(T." ~ member ~ ") ) ) )
            alias typeof(&T." ~ member ~ ") GetMember;
            alias typeof(T." ~ member ~ ") GetMember;";

Given a type T, returns a typetuple of all members of a class or a struct,
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 .. $]))
        alias T Interleave;

void main() {

    alias object.AssociativeArray!(int,double) T;
//    alias Test T;

    alias Members!T M;
Jul 11 2010