digitalmars.D.learn - How can i increase max number recursive template expansions?
- QAston (3/3) Jul 07 2013 I have a large enum in my code (opcodes for a protocol) - using
- John Colvin (59/62) Jul 07 2013 I don't think you can. Please file a bug report: even though it
- Ellery Newcomer (3/12) Jul 10 2013 or feel free to commandeer this one
- Simen Kjaeraas (54/57) Jul 07 2013 You can't. However, you can amend std.traits.EnumMembers to work
- John Colvin (3/63) Jul 07 2013 We came up with almost identical solutions, posted within 19
- Simen Kjaeraas (5/7) Jul 07 2013 Sorta. Mine does repeated halving, and makes DMD run out of memory with
- John Colvin (2/9) Jul 07 2013 so it does. Yup, yours is betters.
- QAston (2/77) Jul 07 2013 Thanks guys, you're awesome!
- bearophile (4/6) Jul 08 2013 Worth putting in Phobos?
- John Colvin (4/10) Jul 08 2013 I reckon so. It's rare to have such huge structs or classes that
- Simen Kjaeraas (7/11) Jul 08 2013 Filed:
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?
Jul 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.
Jul 07 2013
On 07/07/2013 01:22 PM, John Colvin wrote:On Sunday, 7 July 2013 at 19:55:26 UTC, QAston wrote:or feel free to commandeer this one http://d.puremagic.com/issues/show_bug.cgi?id=6471I 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.
Jul 10 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
Jul 07 2013
On Sunday, 7 July 2013 at 20:22:59 UTC, Simen Kjaeraas wrote:On 2013-07-07, 21:55, QAston wrote:We came up with almost identical solutions, posted within 19 seconds of each other!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.
Jul 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
Jul 07 2013
On Sunday, 7 July 2013 at 20:41:17 UTC, Simen Kjaeraas wrote:On 2013-07-07, 22:28, John Colvin wrote:so it does. Yup, yours is betters.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.
Jul 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:Thanks guys, you're awesome!On 2013-07-07, 21:55, QAston wrote:We came up with almost identical solutions, posted within 19 seconds of each other!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.
Jul 07 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
Jul 08 2013
On Monday, 8 July 2013 at 09:03:24 UTC, bearophile wrote:Simen Kjaeraas: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.However, you can amend std.traits.EnumMembers to work with larger enums by using this version:Worth putting in Phobos? Bye, bearophile
Jul 08 2013
On 2013-07-08, 11:03, bearophile wrote:Simen Kjaeraas: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 -- SimenHowever, you can amend std.traits.EnumMembers to work with larger enums by using this version:Worth putting in Phobos?
Jul 08 2013