digitalmars.D.learn - Min, max of enum
- Profile Anaysis (27/27) Jan 25 2017 Since we do not have attributes for enums, I use _ in front of
- Stefan Koch (4/7) Jan 25 2017 This can be done with Ctfe mixins and __traits,
- Biotronic (110/141) Jan 26 2017 Like Stefan said, __traits(allMembers, myEnum) lets you iterate
Since we do not have attributes for enums, I use _ in front of the names for meta values. I need to get the non-meta values for the enum so I can iterate over it and use it properly. enum myEnum { _Meta1 = 0, A,B,C, _Meta3 = 43, D = 3, } The num, for all practical purposes does not contain _Meta1, and_Meta3. But in code I use to!myEnum(intI) and having the meta values complicate things(simple shifting may or may not work). I also need to create array indexers based on myEnum that don't include the meta characters. What I do a lot is convert integers in to fields of the enum. If I do not include any Meta, then it is straight forward to!myEnum(i), but with them it is not, so doing things like int[myEnum] x; x[to!myEnum(i))] is difficult because the conversion will be invalid for meta. I'd have to do some work on i to get the 0-n representation to map properly in to the enum... basically avoiding the meta fields. This would all be solved with attributes for enums, but that, I suppose is a pipe dream. Any ideas how I can make this easy?
Jan 25 2017
On Thursday, 26 January 2017 at 05:58:26 UTC, Profile Anaysis wrote:Since we do not have attributes for enums, I use _ in front of the names for meta values. [...]This can be done with Ctfe mixins and __traits, look at __traits(allMembers)
Jan 25 2017
On Thursday, 26 January 2017 at 05:58:26 UTC, Profile Anaysis wrote:Since we do not have attributes for enums, I use _ in front of the names for meta values. I need to get the non-meta values for the enum so I can iterate over it and use it properly. enum myEnum { _Meta1 = 0, A,B,C, _Meta3 = 43, D = 3, } The num, for all practical purposes does not contain _Meta1, and_Meta3. But in code I use to!myEnum(intI) and having the meta values complicate things(simple shifting may or may not work). I also need to create array indexers based on myEnum that don't include the meta characters. What I do a lot is convert integers in to fields of the enum. If I do not include any Meta, then it is straight forward to!myEnum(i), but with them it is not, so doing things like int[myEnum] x; x[to!myEnum(i))] is difficult because the conversion will be invalid for meta. I'd have to do some work on i to get the 0-n representation to map properly in to the enum... basically avoiding the meta fields. This would all be solved with attributes for enums, but that, I suppose is a pipe dream. Any ideas how I can make this easy?Like Stefan said, __traits(allMembers, myEnum) lets you iterate over the elements of the enum. For a to!myEnum that ignores _Meta fields, you could do something like this: T toEnum(T)(int n) { foreach (element; __traits(allMembers, myEnum)) { static if (element[0] != '_') { if (n == cast(int)__traits(getMember, myEnum, element)) return __traits(getMember, myEnum, element); } } assert(false); } Looking at your code though, I wonder if the problem you want solved is a different one. Especially this part:I'd have to do some work on i to get the 0-n representation to map properly in to the enum... basically avoiding the meta fields.If I understand you correctly, you want this: enum myEnum { _Meta1 = 0, A,B,C, _Meta3 = 43, D = 3, } to become this: enum myEnum { A = 0, B = 1, C = 2, D = 3 } That's a taller order, especially given that the original is equivalent to this: enum myEnum { A = 1, B = 2, C = 3, D = 3 // And some meta members, but not relevant here. } One option would look somewhat like this: alias myEnum = Enum!q{ _Meta1 = 0, A, B, C, _Meta2 = 43, D }; template Enum(string enumBody) { mixin(generateEnum!enumBody); } string generateEnum(string enumBody)() { import std.conv; string result; mixin("enum members {"~enumBody~"}"); foreach (element; __traits(allMembers, members)) { if (element[0] != '_') { result ~= element ~ ","; } } return " MetaData!\""~enumBody~"\" enum Enum {"~result~"}"; } template MetaData(string enumBody) { mixin(generateMeta!enumBody); } string generateMeta(string enumBody)() { import std.conv; string result; mixin("enum members {"~enumBody~"}"); foreach (element; __traits(allMembers, members)) { if (element[0] == '_') { result ~= element ~ " = " ~ (cast(int)__traits(getMember, members, element)).to!string ~ ","; } } return "enum MetaData {"~result~"}"; } template meta(T) if (is(T == enum)) { import std.typetuple; alias meta = AliasSeq!(__traits(getAttributes, T))[0]; } void main() { import std.stdio; import std.conv; import std.typetuple; writeln(myEnum.A, ": ", cast(int)myEnum.A); writeln(myEnum.B, ": ", cast(int)myEnum.B); writeln(myEnum.C, ": ", cast(int)myEnum.C); writeln(myEnum.D, ": ", cast(int)myEnum.D); writeln(meta!myEnum._Meta1, ":", cast(int)meta!myEnum._Meta1); writeln(meta!myEnum._Meta2, ":", cast(int)meta!myEnum._Meta2); } This lets you define the enum with a somewhat familiar syntax: alias myEnum = Enum!q{ _Meta1 = 0, A, B, C, _Meta2 = 43, D }; and generates from that the equivalent of this: myEnum_Meta enum myEnum { A, B, C, D } enum myEnum_Meta { _Meta1 = 0, _Meta2 = 43 }
Jan 26 2017