Jump to page: 1 2
Thread overview
How can i increase max number recursive template expansions?
Jul 07, 2013
QAston
Jul 07, 2013
John Colvin
Jul 10, 2013
Ellery Newcomer
Jul 07, 2013
Simen Kjaeraas
Jul 07, 2013
John Colvin
Jul 07, 2013
Simen Kjaeraas
Jul 07, 2013
John Colvin
Jul 07, 2013
QAston
Jul 08, 2013
bearophile
Jul 08, 2013
John Colvin
Jul 08, 2013
Simen Kjaeraas
July 07, 2013
I have a large enum in my code (opcodes for a protocol) - using std.traits.EnumMembers gives me a recursive template error.

How can i increase max number recursive template expansions?
July 07, 2013
On Sunday, 7 July 2013 at 19:55:26 UTC, QAston wrote:
> I have a large enum in my code (opcodes for a protocol) - using std.traits.EnumMembers gives me a recursive template error.
>
> How can i increase max number recursive template expansions?

I don't think you can. Please file a bug report: even though it might not get fixed any time soon (other than maybe just upping the threshold), there is talk of enabling more imperative-style programming in templates at the moment, and this would be a good case for it.

Try this as a workaround for now:

import std.typetuple;

template EnumMembersLarge(E)
    if (is(E == enum))
{
    // Supply the specified identifier to an constant value.
    template WithIdentifier(string ident)
    {
        static if (ident == "Symbolize")
        {
            template Symbolize(alias value)
            {
                enum Symbolize = value;
            }
        }
        else
        {
            mixin("template Symbolize(alias "~ ident ~")"
                 ~"{"
                     ~"alias "~ ident ~" Symbolize;"
                 ~"}");
        }
    }

    template EnumSpecificMembers(names...)
    {
        static if (names.length > 0)
        {
            alias TypeTuple!(
                    WithIdentifier!(names[0])
                        .Symbolize!(__traits(getMember, E, names[0])),
                    EnumSpecificMembers!(names[1 .. $])
                ) EnumSpecificMembers;
        }
        else
        {
            alias TypeTuple!() EnumSpecificMembers;
        }
    }

    alias TypeTuple!(EnumSpecificMembers!(__traits(allMembers, E)[0..$/2]),
                     EnumSpecificMembers!(__traits(allMembers, E)[$/2..$])
          EnumMembersLarge;
}

All except the last alias line and the changed name is just copied and pasted from EnumMembers.
As you can see we're doing the recursive template stuff in 2 sections and then splicing them together, halving the recursion depth. The result is exactly equivalent to EnumMembers. If your enum is really huge you could split it up in to thirds or quarters, or even generate the split automatically with a template.
July 07, 2013
On 2013-07-07, 21:55, QAston wrote:

> I have a large enum in my code (opcodes for a protocol) - using std.traits.EnumMembers gives me a recursive template error.
>
> How can i increase max number recursive template expansions?

You can't. However, you can amend std.traits.EnumMembers to work
with larger enums by using this version:



import std.typetuple;

template EnumMembers(E)
    if (is(E == enum))
{
    // Supply the specified identifier to an constant value.
    template WithIdentifier(string ident)
    {
        static if (ident == "Symbolize")
        {
            template Symbolize(alias value)
            {
                enum Symbolize = value;
            }
        }
        else
        {
            mixin("template Symbolize(alias "~ ident ~")"
                 ~"{"
                     ~"alias "~ ident ~" Symbolize;"
                 ~"}");
        }
    }

    template EnumSpecificMembers(names...)
    {
        static if (names.length > 200)
        {
            alias TypeTuple!(
                    EnumSpecificMembers!(names[0..$/2]),
                    EnumSpecificMembers!(names[$/2..$]),
                ) EnumSpecificMembers;
        }
        else static if (names.length > 0)
        {
            alias TypeTuple!(
                    WithIdentifier!(names[0])
                        .Symbolize!(__traits(getMember, E, names[0])),
                    EnumSpecificMembers!(names[1 .. $]),
                ) EnumSpecificMembers;
        }
        else
        {
            alias TypeTuple!() EnumSpecificMembers;
        }
    }

    alias EnumSpecificMembers!(__traits(allMembers, E)) EnumMembers;
}



Here, this line:
        static if (names.length > 200)
uses divide-and-conquer to reduce the number of template instantiations.

-- 
Simen
July 07, 2013
On Sunday, 7 July 2013 at 20:22:59 UTC, Simen Kjaeraas wrote:
> On 2013-07-07, 21:55, QAston wrote:
>
>> I have a large enum in my code (opcodes for a protocol) - using std.traits.EnumMembers gives me a recursive template error.
>>
>> How can i increase max number recursive template expansions?
>
> You can't. However, you can amend std.traits.EnumMembers to work
> with larger enums by using this version:
>
>
>
> import std.typetuple;
>
> template EnumMembers(E)
>     if (is(E == enum))
> {
>     // Supply the specified identifier to an constant value.
>     template WithIdentifier(string ident)
>     {
>         static if (ident == "Symbolize")
>         {
>             template Symbolize(alias value)
>             {
>                 enum Symbolize = value;
>             }
>         }
>         else
>         {
>             mixin("template Symbolize(alias "~ ident ~")"
>                  ~"{"
>                      ~"alias "~ ident ~" Symbolize;"
>                  ~"}");
>         }
>     }
>
>     template EnumSpecificMembers(names...)
>     {
>         static if (names.length > 200)
>         {
>             alias TypeTuple!(
>                     EnumSpecificMembers!(names[0..$/2]),
>                     EnumSpecificMembers!(names[$/2..$]),
>                 ) EnumSpecificMembers;
>         }
>         else static if (names.length > 0)
>         {
>             alias TypeTuple!(
>                     WithIdentifier!(names[0])
>                         .Symbolize!(__traits(getMember, E, names[0])),
>                     EnumSpecificMembers!(names[1 .. $]),
>                 ) EnumSpecificMembers;
>         }
>         else
>         {
>             alias TypeTuple!() EnumSpecificMembers;
>         }
>     }
>
>     alias EnumSpecificMembers!(__traits(allMembers, E)) EnumMembers;
> }
>
>
>
> Here, this line:
>         static if (names.length > 200)
> uses divide-and-conquer to reduce the number of template instantiations.

We came up with almost identical solutions, posted within 19 seconds of each other!
July 07, 2013
On 2013-07-07, 22:28, John Colvin wrote:

> We came up with almost identical solutions, posted within 19 seconds of each other!

Sorta. Mine does repeated halving, and makes DMD run out of memory with
16384 enum members. Yours balks at an enum of > about 1000 elements.

-- 
Simen
July 07, 2013
On Sunday, 7 July 2013 at 20:41:17 UTC, Simen Kjaeraas wrote:
> On 2013-07-07, 22:28, John Colvin wrote:
>
>> We came up with almost identical solutions, posted within 19 seconds of each other!
>
> Sorta. Mine does repeated halving, and makes DMD run out of memory with
> 16384 enum members. Yours balks at an enum of > about 1000 elements.

so it does. Yup, yours is betters.
July 07, 2013
On Sunday, 7 July 2013 at 20:28:12 UTC, John Colvin wrote:
> On Sunday, 7 July 2013 at 20:22:59 UTC, Simen Kjaeraas wrote:
>> On 2013-07-07, 21:55, QAston wrote:
>>
>>> I have a large enum in my code (opcodes for a protocol) - using std.traits.EnumMembers gives me a recursive template error.
>>>
>>> How can i increase max number recursive template expansions?
>>
>> You can't. However, you can amend std.traits.EnumMembers to work
>> with larger enums by using this version:
>>
>>
>>
>> import std.typetuple;
>>
>> template EnumMembers(E)
>>    if (is(E == enum))
>> {
>>    // Supply the specified identifier to an constant value.
>>    template WithIdentifier(string ident)
>>    {
>>        static if (ident == "Symbolize")
>>        {
>>            template Symbolize(alias value)
>>            {
>>                enum Symbolize = value;
>>            }
>>        }
>>        else
>>        {
>>            mixin("template Symbolize(alias "~ ident ~")"
>>                 ~"{"
>>                     ~"alias "~ ident ~" Symbolize;"
>>                 ~"}");
>>        }
>>    }
>>
>>    template EnumSpecificMembers(names...)
>>    {
>>        static if (names.length > 200)
>>        {
>>            alias TypeTuple!(
>>                    EnumSpecificMembers!(names[0..$/2]),
>>                    EnumSpecificMembers!(names[$/2..$]),
>>                ) EnumSpecificMembers;
>>        }
>>        else static if (names.length > 0)
>>        {
>>            alias TypeTuple!(
>>                    WithIdentifier!(names[0])
>>                        .Symbolize!(__traits(getMember, E, names[0])),
>>                    EnumSpecificMembers!(names[1 .. $]),
>>                ) EnumSpecificMembers;
>>        }
>>        else
>>        {
>>            alias TypeTuple!() EnumSpecificMembers;
>>        }
>>    }
>>
>>    alias EnumSpecificMembers!(__traits(allMembers, E)) EnumMembers;
>> }
>>
>>
>>
>> Here, this line:
>>        static if (names.length > 200)
>> uses divide-and-conquer to reduce the number of template instantiations.
>
> We came up with almost identical solutions, posted within 19 seconds of each other!

Thanks guys, you're awesome!
July 08, 2013
Simen Kjaeraas:

> However, you can amend std.traits.EnumMembers to work
> with larger enums by using this version:

Worth putting in Phobos?

Bye,
bearophile
July 08, 2013
On Monday, 8 July 2013 at 09:03:24 UTC, bearophile wrote:
> Simen Kjaeraas:
>
>> However, you can amend std.traits.EnumMembers to work
>> with larger enums by using this version:
>
> Worth putting in Phobos?
>
> Bye,
> bearophile

I reckon so. It's rare to have such huge structs or classes that this sort of this becomes a problem for them, but massive enums are reasonably common.
July 08, 2013
On 2013-07-08, 11:03, bearophile wrote:

> Simen Kjaeraas:
>
>> However, you can amend std.traits.EnumMembers to work
>> with larger enums by using this version:
>
> Worth putting in Phobos?

Filed:

http://d.puremagic.com/issues/show_bug.cgi?id=10569

And created a pull request:

https://github.com/D-Programming-Language/phobos/pull/1400

-- 
Simen
« First   ‹ Prev
1 2