Thread overview
Reflection: is type an inner class
Oct 21, 2012
Andrej Mitrovic
Oct 21, 2012
Jonathan M Davis
Oct 21, 2012
Andrej Mitrovic
October 21, 2012
Say I have something like this:

    class A {
        class B {
        }

        B b;
    }

Right now, I have a loop that does something like this (taken from orange project):

    foreach (i, type; typeof(A.tupleof)) {
        enum name = A.tupleof[i].stringof[1 + A.stringof.length + 2 .. $];
    }

This gets all members of class A (in this case only b), but I can't 'new' the class because it needs the context of the instance of A. So, I need to check (preferably at compile time) if b's type is an inner class or an outer class. If it's an inner class, I'll need to instantiate it with the reference of A.

std.traits doesn't seem to have anything useful. I'd like to know the following:

* is b's type instantiatable (is that a word?) without extra information?
* is b's type an inner class (needs reference to instantiate)

In my code, I have a reference handy, so I just need to know how to instantiate it.

I saw the macro 'compiles' in the traits documentation (__traits(compiles, ...)). Do I need to do something with this?
October 21, 2012
I got it working using compiles:

    A a = new A;
    foreach (i, type; typeof(A.tupleof)) {
        enum name = A.tupleof[i].stringof[1 + A.stringof.length +
2 .. $];
        static if (__traits(compiles, mixin("A." ~ type.stringof))) {
            mixin("a." ~ name) = a.new type;
        } else {
            mixin("a." ~ name) = new type;
        }
    }

It's pretty hacky, but it seems to work. I'd be very interested in a cleaner solution, but this works for now.
October 21, 2012
On 10/21/12, Tyler Jameson Little <beatgammit@gmail.com> wrote:
> Say I have something like this:
>
>      class A {
>          class B {
>          }
>
>          B b;
>      }

I can't find a way to figure out if the inner type is static or not. If it's static you don't need the outer class to instantiate it. Figuring out if it's nested or not is doable:

class A
{
    class B { }
    B b;
}

template GetType(T)
{
    alias T GetType;
}

template GetParentType(alias T)
{
    alias GetType!(__traits(parent, T)) GetParentType;
}

template isInnerClass(T)
{
    enum bool isInnerClass = is(GetParentType!T == class);
}

void main()
{
    A.B ab;
    static assert(isInnerClass!(typeof(ab)));
}

(P.S. to others, why is __traits so impossible to work with? typeof can't be used to extract the type, I had to write a special template just to extract the type of a symbol..)
October 21, 2012
I hope this isn't a double post, I'm posting from the web ui. I got this working using __traits(compiles):

    A a = new A;
    static if (is(A == class)) {
        alias TypeTuple!(A, BaseClassesTuple!A) Types;
    } else {
        alias TypeTuple!A Types;
    }

    foreach (BT; Types) {
        foreach (i, type; typeof(BT.tupleof)) {
            enum name = BT.tupleof[i].stringof[1 + BT.stringof.length + 2 .. $];

            if (!mixin("ret." ~ name)) {
                static if (__traits(compiles, mixin("BT." ~ type.stringof))) {
                    mixin("a." ~ name) = ret.new type;
                } else {
                    mixin("a." ~ name) = new type;
                }
            }
        }
    }

This is the basic idea. I've omitted a bunch of the irrelevant code for brevity.  The following structure gets initialized correctly:

    class A {
        class B {
            class C {
                int d;
            }
            C c;
        }
        B b;
    }

Is this the best way to do this, or is there a cleaner, type independent way?  I'm doing this for a JSON marshaller I'm working on.
October 21, 2012
On Sunday, October 21, 2012 05:39:54 Andrej Mitrovic wrote:
> On 10/21/12, Tyler Jameson Little <beatgammit@gmail.com> wrote:
> > Say I have something like this:
> > class A {
> > 
> > class B {
> > }
> > 
> > B b;
> > 
> > }
> 
> I can't find a way to figure out if the inner type is static or not.

How about checking whether it has an outer property? IIRC, B should have a .outer which refers to the instantiation of A that holds it, since it's non-static, whereas if it were static, there would be no such property.

- Jonathan M Davis
October 21, 2012
On Sunday, 21 October 2012 at 03:40:15 UTC, Andrej Mitrovic wrote:
> On 10/21/12, Tyler Jameson Little <beatgammit@gmail.com> wrote:
>> Say I have something like this:
>>
>>      class A {
>>          class B {
>>          }
>>
>>          B b;
>>      }
>
> I can't find a way to figure out if the inner type is static or not.
> If it's static you don't need the outer class to instantiate it.
> Figuring out if it's nested or not is doable:
>
> class A
> {
>     class B { }
>     B b;
> }
>
> template GetType(T)
> {
>     alias T GetType;
> }
>
> template GetParentType(alias T)
> {
>     alias GetType!(__traits(parent, T)) GetParentType;
> }
>
> template isInnerClass(T)
> {
>     enum bool isInnerClass = is(GetParentType!T == class);
> }
>
> void main()
> {
>     A.B ab;
>     static assert(isInnerClass!(typeof(ab)));
> }
>
> (P.S. to others, why is __traits so impossible to work with? typeof
> can't be used to extract the type, I had to write a special template
> just to extract the type of a symbol..)

Hmm, maybe something like this should go into std.traits? This seems more readable than my hacky solution (__traits(compiles, A.B)).
October 21, 2012
On 10/21/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> How about checking whether it has an outer property?

outer could be a user-defined property/enum.