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)
    {
        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);
}
Jul 11 2010