digitalmars.D - Design of reflective enums
- renoX (20/20) Feb 19 2007 Hello,
- Michiel (10/15) Feb 19 2007 What about this one:
- Michiel (4/9) Feb 19 2007 By the way, should this not be in the core language?
- renoX (198/207) Feb 19 2007 Well I think that Ada does it in the core language (but I think that the...
- Andrei Alexandrescu (See Website For Email) (5/18) Feb 19 2007 On the contrary, I think it would be great if it were _not_ in the core
- Michiel (9/20) Feb 19 2007 That's a strange thing to hope for. There are advantages to having a
- Andrei Alexandrescu (See Website For Email) (10/31) Feb 19 2007 These particular advantages don't come forward in the case of enums.
- Serg Kovrov (8/11) Feb 23 2007 It's a great idea! But there are few issues that should be addressed:
- renoX (5/16) Feb 23 2007 This is doable, unfortunately function overload on typedef/enum seems
- Michiel (5/9) Feb 23 2007 Not if it's a core feature. Every request for a label could be replaced
- renoX (9/17) Feb 23 2007 I think that we do not understand, I'm talking about 'reflective enums'
- Michiel (6/21) Feb 24 2007 Yes, but it wouldn't be a symbol. Like I said, a request for a label
- Daniel Keep (22/41) Feb 24 2007 The key here is *at runtime*.
- Andrei Alexandrescu (See Website For Email) (7/15) Feb 19 2007 Why? There is so much more freedom now, why limit ourselves. I think
- renoX (14/36) Feb 19 2007 Because that way a programmer used to normal enums can use reflective
- Kevin Bealer (64/91) Feb 19 2007 Your comment about e and f matches something I've been thinking. The
- renoX (6/57) Feb 20 2007 Agreed, in fact we don't need toString functions, the arrays are enough.
- renoX (15/15) Feb 20 2007 I've ran into trouble trying to implement the associative array:
- Kevin Bealer (23/42) Feb 20 2007 I want to make clear -- efficiency is important to me, at least if this
Hello, Kevin Bealer has started an implementation (two implementations in fact!) of reflective enums, and I wanted to discuss the use case and the design of this feature to make it as useful as possible. Reflective enums have two useful properties that don't have normal enums: - their label is printable - it's possible to do a foreach on all the possible values. In my opinion, for the reflective enums, the following constraint should apply: - they should 'look like' normal enums as much as possible. - then the printable label feature should be as simple to use as possible: this feature will probably be used much more often than the foreach feature. For the API, the functions needed are: a- Reflective Enum(REnum) list definition. b. REnum variable definition. c. Reference to an REnum label. d. Print the label corresponding to the value of an REnum variable. e. Iterate over all possible value in an REnum list. f. Iterate over all possible labels in an REnum list (I've added this one by symmetry). (a) Takes a name and either define (1) an enum of this name plus some functions to print enum labels and iterate over it, or alternatively as in the original code it can return a 'thing' (struct for example as it in the initial implementation) (2) which contain the enum and functions. I'm not sure which is best. (e) and (f) reminds me of associate arrays, maybe a function to generate an associative array from the enum list would be enough.. I'm trying to create functions to (e) and (f), but I have trouble to make my code work currently: debugging template code is not very easy.. renoX
Feb 19 2007
renoX wrote:Hello, Kevin Bealer has started an implementation (two implementations in fact!) of reflective enums, and I wanted to discuss the use case and the design of this feature to make it as useful as possible. Reflective enums have two useful properties that don't have normal enums: - their label is printable - it's possible to do a foreach on all the possible values.What about this one: - it's possible to do a slice and get a new enum with a subset of the original enum values (and labels) You could do something like this: enum Weekday {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY} foreach (day; Weekday[MONDAY..FRIDAY]) { ... } -- Michiel
Feb 19 2007
renoX wrote:Hello, Kevin Bealer has started an implementation (two implementations in fact!) of reflective enums, and I wanted to discuss the use case and the design of this feature to make it as useful as possible. Reflective enums have two useful properties that don't have normal enums: - their label is printable - it's possible to do a foreach on all the possible values.By the way, should this not be in the core language? -- Michiel
Feb 19 2007
Michiel Wrote:renoX wrote:Well I think that Ada does it in the core language (but I think that they are not printable), it is able to define enum as an index array as you suggest in your second email. As the more I look at D, the more I find it similar to Ada, it is perhaps a good idea to make them those enhanced enum in the core language, and as an improvement to Ada those enum should be printable (maybe as an option to save memory) . In the meantime, my trial is below, but it doesn't work when there are two enums: the two toString conflicts, even though they should not because their parameter is a different enum type. Should I report this as a bug? renoX import std.stdio; import std.metastrings; template Find(char[] A, char[] B) { static if (A.length < B.length) { const int Find = -1; } else static if (A[0..B.length] == B) { const int Find = 0; } else static if (-1 == Find!(A[1..$], B)) { const int Find = -1; } else { const int Find = 1 + Find!(A[1..$], B); } } template SplitFirst(char[] A, char[] B) { const int Location = Find!(A, B); static if (Location == -1) { const char[] First = A; const char[] Rest = ""; } else { const char[] First = A[0..Location]; const char[] Rest = A[Location+B.length..$]; } } template ChompSpaces(char[] A) { static if (A.length) { static if (A[0] == ' ') { alias ChompSpaces!(A[1..$]) ChompSpaces; } else static if (A[$-1] == ' ') { alias ChompSpaces!(A[0..$-1]) ChompSpaces; } else { alias A ChompSpaces; } } else { const char[] ChompSpaces = ""; } } template SplitChomp(char[] A, char[] B) { alias ChompSpaces!(SplitFirst!(A, B).First) First; alias ChompSpaces!(SplitFirst!(A, B).Rest) Rest; } template EnumName(char[] A) { alias SplitChomp!(SplitFirst!(A, ",").First, "=").First EnumName; } template EnumAssign(char[] A) { alias SplitChomp!(SplitFirst!(A, ",").First, "=").Rest EnumAssign; } template EnumValue(char[] A, int i) { static if (EnumAssign!(A) == "") { const int EnumValue = i; } else { const int EnumValue = mixin(ParseInteger!(EnumAssign!(A)).value); } } template EnumListName(char[] A) { alias SplitChomp!(A, "{").First EnumListName; } template EnumBody(char[] A) { alias SplitChomp!(SplitFirst!(A, "}").First, "{").Rest EnumBody; } template BuildOneEnum(char[] A, int i) { const char[] BuildOneEnum = "const int "~EnumName!(A)~" = "~ ToString!(EnumValue!(A, i))~";\n"; } template BuildEnums(char[] A, int i) { static if (SplitChomp!(A, ",").Rest.length == 0) { const char[] BuildEnums = BuildOneEnum!(A, EnumValue!(A, i)); } else { const char[] BuildEnums = BuildOneEnum!(SplitChomp!(A, ",").First, EnumValue!(A, i)) ~ BuildEnums!(SplitChomp!(A, ",").Rest, EnumValue!(A, i)+1); } } template BuildOneCase(char[] A, int i, bool full) { static if (!full) { const char[] BuildOneCase = "case "~ToString!(EnumValue!(A, i))~ ": return \""~EnumName!(A)~"\";\n"; } else { const char[] BuildOneCase = "case "~ToString!(EnumValue!(A, i))~ ": return \""~EnumName!(A)~"("~ToString!(EnumValue!(A, i))~")\";\n"; } } template BuildEnumCases(char[] A, int i, bool full) { static if (SplitChomp!(A, ",").Rest.length == 0) { const char[] BuildEnumCases = BuildOneCase!(A, EnumValue!(A, i), full); } else { const char[] BuildEnumCases = BuildOneCase!(SplitChomp!(A, ",").First, EnumValue!(A, i), full) ~ BuildEnumCases!(SplitChomp!(A, ",").Rest, EnumValue!(A, i)+1,full); } } template BuildEnumSwitch(char[] A, int i, bool full) { const char[] BuildEnumSwitch = "switch(x) {"~ BuildEnumCases!(A, i, full) ~ "default: "~ " throw new Exception(\"enumeration out of range\");" "}"; } template BuildEnumElem(char[] A, char[]enumListName, int i, int ekv) { static if (ekv == 0) { const char[] BuildEnumElem = enumListName~"."~EnumName!(A)~", "; } ; static if (ekv == 1) { const char[] BuildEnumElem = "\""~EnumName!(A)~"\", "; }; static if (ekv == 2) { const char[] BuildEnumElem = ToString!(EnumValue!(A, i))~", "; } } // build the list of key if key is true, the list of values if key is false template BuildEnumList(char[] A, char[]enumListName, int i, int ekv) { static if (SplitChomp!(A, ",").Rest.length == 0) { const char[] BuildEnumList = BuildEnumElem!(A, enumListName, EnumValue!(A, i), ekv); } else { const char[] BuildEnumList = BuildEnumElem!(SplitChomp!(A, ",").First, enumListName, EnumValue!(A, i), ekv)~ BuildEnumList!(SplitChomp!(A, ",").Rest, enumListName, EnumValue!(A, i)+1, ekv); } } //to be mature it should parse also the EnumBaseType template DefEnum(char[] enum_str) { mixin("enum "~enum_str~";"); mixin( "static char[] toString("~EnumListName!(enum_str)~" val) { int x = val; "~ BuildEnumSwitch!(EnumBody!(enum_str), 0, false)~ " }" ); mixin( "static char[] toFullString("~EnumListName!(enum_str)~" val) { int x = val; "~ BuildEnumSwitch!(EnumBody!(enum_str), 0, true)~ " }" ); mixin( "const "~EnumListName!(enum_str)~"[] "~EnumListName!(enum_str)~"_elem ="~ " [ "~ BuildEnumList!(EnumBody!(enum_str), EnumListName!(enum_str), 0, 0)~ " ];" ); mixin( "const char[][]"~EnumListName!(enum_str)~"_keys = [ "~ BuildEnumList!(EnumBody!(enum_str), EnumListName!(enum_str), 0, 1)~ " ];" ); mixin( "const int[]"~EnumListName!(enum_str)~"_values = [ "~ BuildEnumList!(EnumBody!(enum_str), EnumListName!(enum_str), 0, 2)~ " ];" ); } int main(char[][] args) { // mixin DefEnum!("LEnum2 {other=2, cont, end2=15, ps}"); mixin DefEnum!("LEnum {start, middle, end=10, ps, pps,}"); LEnum s = LEnum.start; writefln("s is %s, with name %s full name '%s'\n", s, toString(s), toFullString(s)); foreach(i,v; LEnum_elem) { writefln("Enum %d has name=%s value %d", i, toString(v), v); } // LEnum2 o = LEnum2.other; // writefln("o is %s, with name %s full name '%s'\n", o, toString(o), toFullString(o)); foreach(i,v; LEnum_keys) { writefln("Enum %d has name=%s and value %d", i, v, LEnum_values[i]); } foreach(i,v; LEnum_values) { writefln("Enum %d has name=%s value %d", i, toString(cast(LEnum)v), v); } return 0; }Hello, Kevin Bealer has started an implementation (two implementations in fact!) of reflective enums, and I wanted to discuss the use case and the design of this feature to make it as useful as possible. Reflective enums have two useful properties that don't have normal enums: - their label is printable - it's possible to do a foreach on all the possible values.By the way, should this not be in the core language?
Feb 19 2007
renoX wrote:Michiel Wrote:On the contrary, I think it would be great if it were _not_ in the core language, and I'd be happy if a library enum was so good, it would cause deprecation of the built-in one. AndreirenoX wrote:Well I think that Ada does it in the core language (but I think that they are not printable), it is able to define enum as an index array as you suggest in your second email. As the more I look at D, the more I find it similar to Ada, it is perhaps a good idea to make them those enhanced enum in the core language, and as an improvement to Ada those enum should be printable (maybe as an option to save memory) .Hello, Kevin Bealer has started an implementation (two implementations in fact!) of reflective enums, and I wanted to discuss the use case and the design of this feature to make it as useful as possible. Reflective enums have two useful properties that don't have normal enums: - their label is printable - it's possible to do a foreach on all the possible values.By the way, should this not be in the core language?
Feb 19 2007
Andrei Alexandrescu (See Website For Email) wrote:That's a strange thing to hope for. There are advantages to having a feature in the core language instead of a library. Several of them are summed up on the website. In this case: * The syntax will be nice and clean. * The compiler knows exactly what you mean and can optimize accordingly. Those are not true of library implementations. -- MichielWell I think that Ada does it in the core language (but I think that they are not printable), it is able to define enum as an index array as you suggest in your second email. As the more I look at D, the more I find it similar to Ada, it is perhaps a good idea to make them those enhanced enum in the core language, and as an improvement to Ada those enum should be printable (maybe as an option to save memory) .On the contrary, I think it would be great if it were _not_ in the core language, and I'd be happy if a library enum was so good, it would cause deprecation of the built-in one.
Feb 19 2007
Michiel wrote:Andrei Alexandrescu (See Website For Email) wrote:These particular advantages don't come forward in the case of enums. Core language features also have a lot of disadvantages, such as increasing the size of the language's definition, making the feature inherently rigid and hard to evolve, and putting the onus on the language implementer. I see how strings can be meaningfully made part of the language, but instead of beefing up enums to the behemoth they are in Java, it's much more attractive to allowing libraries to do that. AndreiThat's a strange thing to hope for. There are advantages to having a feature in the core language instead of a library. Several of them are summed up on the website. In this case: * The syntax will be nice and clean. * The compiler knows exactly what you mean and can optimize accordingly. Those are not true of library implementations.Well I think that Ada does it in the core language (but I think that they are not printable), it is able to define enum as an index array as you suggest in your second email. As the more I look at D, the more I find it similar to Ada, it is perhaps a good idea to make them those enhanced enum in the core language, and as an improvement to Ada those enum should be printable (maybe as an option to save memory) .On the contrary, I think it would be great if it were _not_ in the core language, and I'd be happy if a library enum was so good, it would cause deprecation of the built-in one.
Feb 19 2007
Andrei Alexandrescu (See Website For Email) wrote:On the contrary, I think it would be great if it were _not_ in the core language, and I'd be happy if a library enum was so good, it would cause deprecation of the built-in one.It's a great idea! But there are few issues that should be addressed: 1. Library implementation of enums should be able to produce a typedef, just like built-in enums. 2. Built-in enums do not produce symbols in object files. Neither should library implementation. -- serg.
Feb 23 2007
Serg Kovrov a écrit :Andrei Alexandrescu (See Website For Email) wrote:This is doable, unfortunately function overload on typedef/enum seems broken, so..On the contrary, I think it would be great if it were _not_ in the core language, and I'd be happy if a library enum was so good, it would cause deprecation of the built-in one.It's a great idea! But there are few issues that should be addressed: 1. Library implementation of enums should be able to produce a typedef, just like built-in enums.2. Built-in enums do not produce symbols in object files. Neither should library implementation.Well for reflective enums, you need to store the strings somewhere.. renoX
Feb 23 2007
renoX wrote:Not if it's a core feature. Every request for a label could be replaced by a literal by the compiler. -- Michiel2. Built-in enums do not produce symbols in object files. Neither should library implementation.Well for reflective enums, you need to store the strings somewhere..
Feb 23 2007
Michiel a écrit :renoX wrote:I think that we do not understand, I'm talking about 'reflective enums' not regular enums (after all the thread is 'design of reflective enums). Reflective are enums where you can print also the *label* associated with the enum, so there must be a function somewhere which have these label strings to be able to print the label at runtime. So the label strings must be of course stored in the binary for reflective enums. renoXNot if it's a core feature. Every request for a label could be replaced by a literal by the compiler.2. Built-in enums do not produce symbols in object files. Neither should library implementation.Well for reflective enums, you need to store the strings somewhere..
Feb 23 2007
renoX wrote:Yes, but it wouldn't be a symbol. Like I said, a request for a label could be replaced by a string literal by the compiler IF reflective enums were a core language feature. -- MichielI think that we do not understand, I'm talking about 'reflective enums' not regular enums (after all the thread is 'design of reflective enums). Reflective are enums where you can print also the *label* associated with the enum, so there must be a function somewhere which have these label strings to be able to print the label at runtime. So the label strings must be of course stored in the binary for reflective enums.Not if it's a core feature. Every request for a label could be replaced by a literal by the compiler.2. Built-in enums do not produce symbols in object files. Neither should library implementation.Well for reflective enums, you need to store the strings somewhere..
Feb 24 2007
Michiel wrote:renoX wrote:The key here is *at runtime*. enum CompressionLevel { None = 0, Minimal = 1, Normal = 2, Maximal = 3 } { CompressionLevel cl = some_function(); writefln( toFullString(cl) ); } In order for the toFullString function to work, the string must be stored somewhere in the executable so that it is accessible at runtime. At least, I think that's what renoX is talking about :3 -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/Yes, but it wouldn't be a symbol. Like I said, a request for a label could be replaced by a string literal by the compiler IF reflective enums were a core language feature.I think that we do not understand, I'm talking about 'reflective enums' not regular enums (after all the thread is 'design of reflective enums). Reflective are enums where you can print also the *label* associated with the enum, so there must be a function somewhere which have these label strings to be able to print the label at runtime. So the label strings must be of course stored in the binary for reflective enums.Not if it's a core feature. Every request for a label could be replaced by a literal by the compiler.2. Built-in enums do not produce symbols in object files. Neither should library implementation.Well for reflective enums, you need to store the strings somewhere..
Feb 24 2007
renoX wrote:Hello, Kevin Bealer has started an implementation (two implementations in fact!) of reflective enums, and I wanted to discuss the use case and the design of this feature to make it as useful as possible. Reflective enums have two useful properties that don't have normal enums: - their label is printable - it's possible to do a foreach on all the possible values. In my opinion, for the reflective enums, the following constraint should apply: - they should 'look like' normal enums as much as possible.Why? There is so much more freedom now, why limit ourselves. I think enums of arbitrary types should be allowed, including arrays, hashes, and user-defined types. An enumerated type is nothing but a closed set of named values. The names are always strings; the values can be of any (uniform) type. Andrei
Feb 19 2007
Andrei Alexandrescu (See Website For Email) a écrit :renoX wrote:Because that way a programmer used to normal enums can use reflective enums nearly identically.Hello, Kevin Bealer has started an implementation (two implementations in fact!) of reflective enums, and I wanted to discuss the use case and the design of this feature to make it as useful as possible. Reflective enums have two useful properties that don't have normal enums: - their label is printable - it's possible to do a foreach on all the possible values. In my opinion, for the reflective enums, the following constraint should apply: - they should 'look like' normal enums as much as possible.Why?There is so much more freedom now, why limit ourselves. I think enums of arbitrary types should be allowed, including arrays, hashes, and user-defined types.This would be a possible extension, but I wonder if it wouldn't be a bit redundant with associative array.. And I think that with the current implementation, it's would be very difficult,as we do our own parsing which is of course quite limited. Mmm, with this extension, my idea of reusing the built-in enum type doesn't work.. Kevin Bealer's implementation would work.. I'll try to tweak it to see if it's possible to make it feel more enum-like.An enumerated type is nothing but a closed set of named values. The names are always strings; the values can be of any (uniform) type.The names are not arbitrary strings but names/symbol: I wonder if a basic type 'symbol' would be interesting.. renoXAndrei
Feb 19 2007
renoX wrote:Hello, Kevin Bealer has started an implementation (two implementations in fact!) of reflective enums, and I wanted to discuss the use case and the design of this feature to make it as useful as possible. Reflective enums have two useful properties that don't have normal enums: - their label is printable - it's possible to do a foreach on all the possible values. In my opinion, for the reflective enums, the following constraint should apply: - they should 'look like' normal enums as much as possible. - then the printable label feature should be as simple to use as possible: this feature will probably be used much more often than the foreach feature. For the API, the functions needed are: a- Reflective Enum(REnum) list definition. b. REnum variable definition. c. Reference to an REnum label. d. Print the label corresponding to the value of an REnum variable. e. Iterate over all possible value in an REnum list. f. Iterate over all possible labels in an REnum list (I've added this one by symmetry). (a) Takes a name and either define (1) an enum of this name plus some functions to print enum labels and iterate over it, or alternatively as in the original code it can return a 'thing' (struct for example as it in the initial implementation) (2) which contain the enum and functions. I'm not sure which is best. (e) and (f) reminds me of associate arrays, maybe a function to generate an associative array from the enum list would be enough.. I'm trying to create functions to (e) and (f), but I have trouble to make my code work currently: debugging template code is not very easy.. renoXYour comment about e and f matches something I've been thinking. The action of iterating over the enum and in fact looking up the string are essentially similar to an associative array. Imagine these two definitions in regular D: enum Xyz_t { x = 10, y = 100, z = 201 }; char[][Xyz_t] Xyz_t_lookup; lookup[x] = "x"; lookup[y] = "y"; lookup[z] = "z"; Xyz_t[] Xyz_t_keys = Xyz_t_lookup.keys; char[][] Xyz_t_labels = ["x", "y", "z"]; Now, I can do all the above operations with these definitions. We could build a reflective enum that converted to this definition. The main thing that I would change is that instead of a regular associative array, we can define a compile-time associative array. We can be more efficient in a CTAA than an AA because all values are known at compile time -- we convert all lookups to switches. It would look like this: // given types T1 and T2 // constructed like this: // CTAA!(int, char[], "10, \"x\", 100, \"y\", 201, \"z\""); struct CTAA(T1, T2, E... values) { const T1[] keys = [10,100,201]; const T2[] values = ["x","y","z"]; int opApply(int delegate(T1 k, T2 label) dg) { int rv; rv = dg(10, "x"); if (rv) return rv; rv = dg(100, "y"); if (rv) return rv; rv = dg(201, "z"); if (rv) return rv; return 0; } T1 getKey(T2 label) { switch(label) { case "x": return 10; case "y": return 100; case "z": return 201; default: throw new Exception("unknown label"); } } T2 getLabel(T1 key) { switch(label) { case 10: return "x"; case 100: return "y"; case 201: return "z"; default: throw new Exception("unknown enum"); } } } Note that the "\"x\"" stuff is a bit awkward but the reflective enum would be a wrapper around the AA; since it knows that it's 'strings' are just C identifiers, it can omit the escaped quotes in its initializer. Also, since the CTAA is not a real AA there is no reason not to provide the translation in both directions as shown above -- it's not really an AA just a quick way to define a couple of handy switch statements. In principle, switch/case should be more or less always be faster than actual AAs. Kevin
Feb 19 2007
Kevin Bealer Wrote:renoX wrote:Agreed, in fact we don't need toString functions, the arrays are enough. [cut]Hello, Kevin Bealer has started an implementation (two implementations in fact!) of reflective enums, and I wanted to discuss the use case and the design of this feature to make it as useful as possible. Reflective enums have two useful properties that don't have normal enums: - their label is printable - it's possible to do a foreach on all the possible values. In my opinion, for the reflective enums, the following constraint should apply: - they should 'look like' normal enums as much as possible. - then the printable label feature should be as simple to use as possible: this feature will probably be used much more often than the foreach feature. For the API, the functions needed are: a- Reflective Enum(REnum) list definition. b. REnum variable definition. c. Reference to an REnum label. d. Print the label corresponding to the value of an REnum variable. e. Iterate over all possible value in an REnum list. f. Iterate over all possible labels in an REnum list (I've added this one by symmetry). (a) Takes a name and either define (1) an enum of this name plus some functions to print enum labels and iterate over it, or alternatively as in the original code it can return a 'thing' (struct for example as it in the initial implementation) (2) which contain the enum and functions. I'm not sure which is best. (e) and (f) reminds me of associate arrays, maybe a function to generate an associative array from the enum list would be enough.. I'm trying to create functions to (e) and (f), but I have trouble to make my code work currently: debugging template code is not very easy.. renoXYour comment about e and f matches something I've been thinking. The action of iterating over the enum and in fact looking up the string are essentially similar to an associative array. Imagine these two definitions in regular D: enum Xyz_t { x = 10, y = 100, z = 201 }; char[][Xyz_t] Xyz_t_lookup; lookup[x] = "x"; lookup[y] = "y"; lookup[z] = "z"; Xyz_t[] Xyz_t_keys = Xyz_t_lookup.keys; char[][] Xyz_t_labels = ["x", "y", "z"]; Now, I can do all the above operations with these definitions.In principle, switch/case should be more or less always be faster than actual AAs.I must admit that I don't know at all what will be faster at runtime, but in some case the switch/case can be done at compile-time, which is a win. Also if efficiency is a concern, I wonder if it would be useful if in the case when there is no '=' in the enum definition (a not so rare case), we could use a regular array for the lookup (lookup == labels) , the only problem then is that we'd loose type safety for the lookups.. renoX
Feb 20 2007
I've ran into trouble trying to implement the associative array: apparently it's not possible to build an associative array at compile time. Added to that the fact that overloading of functions doesn't work correctly on enums, the implementation of good reflective enum starts to look really difficult.. So it's a choice between -using your initial implementation, which is not typesafe.. -restricting reflective enums to enums without '=' ie with values going 0,1,2.. -waiting that Walter fix the current limitations on associative arrays or the bug(?) on function overloading with enums (overloading with a typedef has the same issue, so maybe it's me who doesn't understand the overload behaviour?).. :-( renoX
Feb 20 2007
renoX wrote:I've ran into trouble trying to implement the associative array: apparently it's not possible to build an associative array at compile time. Added to that the fact that overloading of functions doesn't work correctly on enums, the implementation of good reflective enum starts to look really difficult.. So it's a choice between -using your initial implementation, which is not typesafe.. -restricting reflective enums to enums without '=' ie with values going 0,1,2.. -waiting that Walter fix the current limitations on associative arrays or the bug(?) on function overloading with enums (overloading with a typedef has the same issue, so maybe it's me who doesn't understand the overload behaviour?).. :-( renoXI want to make clear -- efficiency is important to me, at least if this is to be a replacement for enum, efficiency should be as much as is attainable, which should be a lot if it happens at compile time. Just to clarify my previous idea, when I say 'CTAA', I don't mean building a real AA at compile time. I mean building something that works like an AA as far as lookups, but the contents are readonly and added to the container at compile time. My idea is to get maximal efficiency of the type that most likely can't be had with a real AA. The ultimate efficiency in this case would be to have *lookup* happen at compile time for users of the class, though this can only happen in those cases where the search term is constant at compile time. In other cases, something like a switch would be my preference. Of course for the case of a reflective enum, looking up the label is probably not too common so it could be done some other way, but I'm thinking the CTAA should be as fast as possible. What I'm imagining is something like this: CTAA!("dog, bear, cat, snake, whiskey, soda") foo; const char[] x = foo.find!("dog")(); // A const char[] x = "bear"; // B My hope is for a design where statement A is transformed into statement B at compile time. Kevin
Feb 20 2007