Thread overview
How to implement this?
Jun 10, 2013
Elvis
Jun 10, 2013
Benjamin Thaut
Jun 10, 2013
Kenji Hara
Jun 11, 2013
Elvis
Jun 11, 2013
H. S. Teoh
June 10, 2013
class A
{
    enum TypeID = 1;
}
class B : A
{
    enum TypeID = 2;
}

class C : A
{
    enum TypeID = 3;
}

class D : B
{
    enum TypeID = 4;
}

...


Could anybody shed some light on how to make these TypeIDs auto increment at compile time?


June 10, 2013
Am 10/06/2013 11:42, schrieb Elvis:
> class A
> {
>      enum TypeID = 1;
> }
> class B : A
> {
>      enum TypeID = 2;
> }
>
> class C : A
> {
>      enum TypeID = 3;
> }
>
> class D : B
> {
>      enum TypeID = 4;
> }
>
> ...
>
>
> Could anybody shed some light on how to make these TypeIDs auto
> increment at compile time?
>
>

Thats not possible due to the compilation model. You can however do:

alias TypeTuple!(A, B, C, D) list;

class A
{
   enum TypeID = staticIndexOf!(typeof(this), list);
}

class B
{
   enum TypeID = staticIndexOf!(typeof(this), list);
}

Further you could write yoruself a helper template which calls staticIndexOf and does a static assert in case it returns -1 (type not found).

Kind Regards
Benjamin Thaut
June 10, 2013
On Monday, 10 June 2013 at 09:42:56 UTC, Elvis wrote:
> class A
> {
>     enum TypeID = 1;
> }
> class B : A
> {
>     enum TypeID = 2;
> }
>
> class C : A
> {
>     enum TypeID = 3;
> }
>
> class D : B
> {
>     enum TypeID = 4;
> }
>
> ...
>
>
> Could anybody shed some light on how to make these TypeIDs auto increment at compile time?

version(A)
{
    class A
    {
         enum TypeID = 1;
    }

    template IncrementTypeID(Class)
    {
        class IncrementTypeID : Class
        {
            enum TypeID = Class.TypeID + 1;
        }
    }
    alias B = IncrementTypeID!A;
    alias C = IncrementTypeID!B;
    alias D = IncrementTypeID!C;
}
version(B)  // more generative way
{
    template MakeContinuousClasses(int endID)
    {
        static if (endID > 0)
        {
            mixin MakeContinuousClasses!(endID - 1);

            enum className = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[endID - 1];
            static if (endID == 1)
                enum baseClass = "";
            else
                enum baseClass = " : " ~ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[endID - 2];

            import std.conv : to;
            mixin("class "~className~baseClass~" { enum TypeID = "~endID.to!string~"; }");
        }
    }
    mixin MakeContinuousClasses!4;
}

// test case
import std.traits;
pragma(msg, A.TypeID, ", ", BaseClassesTuple!A);  // 1, (Object)
pragma(msg, B.TypeID, ", ", BaseClassesTuple!B);  // 2, (A, Object)
pragma(msg, C.TypeID, ", ", BaseClassesTuple!C);  // 3, (B, A, Object)
pragma(msg, D.TypeID, ", ", BaseClassesTuple!D);  // 4, (C, B, A, Object)

Kenji Hara
June 11, 2013
On Monday, 10 June 2013 at 14:40:05 UTC, Kenji Hara wrote:
> On Monday, 10 June 2013 at 09:42:56 UTC, Elvis wrote:
>> class A
>> {
>>    enum TypeID = 1;
>> }
>> class B : A
>> {
>>    enum TypeID = 2;
>> }
>>
>> class C : A
>> {
>>    enum TypeID = 3;
>> }
>>
>> class D : B
>> {
>>    enum TypeID = 4;
>> }
>>
>> ...
>>
>>
>> Could anybody shed some light on how to make these TypeIDs auto increment at compile time?
>
> version(A)
> {
>     class A
>     {
>          enum TypeID = 1;
>     }
>
>     template IncrementTypeID(Class)
>     {
>         class IncrementTypeID : Class
>         {
>             enum TypeID = Class.TypeID + 1;
>         }
>     }
>     alias B = IncrementTypeID!A;
>     alias C = IncrementTypeID!B;
>     alias D = IncrementTypeID!C;
> }
> version(B)  // more generative way
> {
>     template MakeContinuousClasses(int endID)
>     {
>         static if (endID > 0)
>         {
>             mixin MakeContinuousClasses!(endID - 1);
>
>             enum className = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[endID - 1];
>             static if (endID == 1)
>                 enum baseClass = "";
>             else
>                 enum baseClass = " : " ~ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[endID - 2];
>
>             import std.conv : to;
>             mixin("class "~className~baseClass~" { enum TypeID = "~endID.to!string~"; }");
>         }
>     }
>     mixin MakeContinuousClasses!4;
> }
>
> // test case
> import std.traits;
> pragma(msg, A.TypeID, ", ", BaseClassesTuple!A);  // 1, (Object)
> pragma(msg, B.TypeID, ", ", BaseClassesTuple!B);  // 2, (A, Object)
> pragma(msg, C.TypeID, ", ", BaseClassesTuple!C);  // 3, (B, A, Object)
> pragma(msg, D.TypeID, ", ", BaseClassesTuple!D);  // 4, (C, B, A, Object)
>
> Kenji Hara

Thank you, however both versions are not applicable, you need give them some type of orders manully in version A while class names are suppose to be more generic in real project other than just A to Z in version B.
June 11, 2013
On Tue, Jun 11, 2013 at 02:34:37PM +0200, Elvis wrote:
> On Monday, 10 June 2013 at 14:40:05 UTC, Kenji Hara wrote:
> >On Monday, 10 June 2013 at 09:42:56 UTC, Elvis wrote:
> >>class A
> >>{
> >>   enum TypeID = 1;
> >>}
> >>class B : A
> >>{
> >>   enum TypeID = 2;
> >>}
> >>
> >>class C : A
> >>{
> >>   enum TypeID = 3;
> >>}
> >>
> >>class D : B
> >>{
> >>   enum TypeID = 4;
> >>}
> >>
> >>...
> >>
> >>
> >>Could anybody shed some light on how to make these TypeIDs auto increment at compile time?
> >
> >version(A)
> >{
> >    class A
> >    {
> >         enum TypeID = 1;
> >    }
> >
> >    template IncrementTypeID(Class)
> >    {
> >        class IncrementTypeID : Class
> >        {
> >            enum TypeID = Class.TypeID + 1;
> >        }
> >    }
> >    alias B = IncrementTypeID!A;
> >    alias C = IncrementTypeID!B;
> >    alias D = IncrementTypeID!C;
> >}
> >version(B)  // more generative way
> >{
> >    template MakeContinuousClasses(int endID)
> >    {
> >        static if (endID > 0)
> >        {
> >            mixin MakeContinuousClasses!(endID - 1);
> >
> >            enum className = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[endID -
> >1];
> >            static if (endID == 1)
> >                enum baseClass = "";
> >            else
> >                enum baseClass = " : " ~
> >"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[endID - 2];
> >
> >            import std.conv : to;
> >            mixin("class "~className~baseClass~" { enum TypeID =
> >"~endID.to!string~"; }");
> >        }
> >    }
> >    mixin MakeContinuousClasses!4;
> >}
> >
> >// test case
> >import std.traits;
> >pragma(msg, A.TypeID, ", ", BaseClassesTuple!A);  // 1, (Object)
> >pragma(msg, B.TypeID, ", ", BaseClassesTuple!B);  // 2, (A,
> >Object)
> >pragma(msg, C.TypeID, ", ", BaseClassesTuple!C);  // 3, (B, A,
> >Object)
> >pragma(msg, D.TypeID, ", ", BaseClassesTuple!D);  // 4, (C, B, A,
> >Object)
> >
> >Kenji Hara
> 
> Thank you, however both versions are not applicable, you need give them some type of orders manully in version A while class names are suppose to be more generic in real project other than just A to Z in version B.

The problem is, when you have separate compilation, how would the compiler know what order to assign the classes? If I define 10 classes in file1.d and 10 classes in file2.d, and they are compiled separately, then the compiler has to way to know what numbers to assign each class. (Remember that compile separately means the compiler never gets to see file1.d and file2.d at the same time, so it can't know how to apply any ordering to the classes defined therein.)


T

-- 
Help a man when he is in trouble and he will remember you when he is in trouble again.