Re: CTFE enums static assert
On 2015-05-15 17:26:50 +, Ali Çehreli said: On 05/15/2015 09:45 AM, Robert M. Münch wrote: Is there a way I can build an ENUM from within the FOREACH? What I want to achive is, that I would like to use: final switch (myEnum) ... Sorry, I don't understand your question. :( Do you want to define an enum at compile time? Then you can use mixins. Do you want to build an enum value inside the foreach? Yes, it is possible as well. Hi, yes to both. I have solved it now like this: enum A {a, b, c}; enum members1 = __traits(allMembers, A); // returns TypeTuple // function that generates a string which is used as a mixin at compile time // result string must conform to syntax as it was hand-written code string generateEnum(T...)(string type){ string code = enum ~ type ~ {; // this is a static foreach (compile time) foreach(m; T){ debug pragma(msg, m ~ ,); // check what code we get at compile time code ~= m ~ ,; } return(code ~ }); } int main(){ A switch_var_a; final switch(switch_var_a){ case A.a: case A.b: case A.c: } mixin(generateEnums!members1(B)); B switch_var_b; final switch(switch_var_b){ case B.a: // case B.b: // if commeted will cause a compiler error case B.c: } return(0); } So, the solution was to use a string mixin. IMO it's a very powerful pattern to build an ENUM at compile time that can be used with a FINAL SWITCH. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: CTFE enums static assert
On 2015-05-04 18:22:17 +, Ali Çehreli said: There are many different kinds of tuples in D, only two of which I can handle: 1) Tuple from std.typecons, which are ordinarily created at run time 2) TypeTuple from std.typetuple, which are compile-time entities The documentation is not clear that __traits(allMembers) returns a TypeTuple, which additionally has a bad name. TypeTuple is great because it enables compile-time foreach (unfortunately, implicitly): foreach (m; __traits(allMembers, A)) { // This body is repeated for each member at compile time } Is there a way I can build an ENUM from within the FOREACH? What I want to achive is, that I would like to use: final switch (myEnum) ... and have myEnum build at compiletime. With this the compiler would give an error whenever I have forgotten to update my code to handle a new case. 2. I'm wondering why members1 doesn't has a type at all. Because it is a TypeTuple of values of various types and even types themselves. But shouldn't be the type than be TypeTuple? -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: CTFE enums static assert
On 05/15/2015 09:45 AM, Robert M. Münch wrote: On 2015-05-04 18:22:17 +, Ali Çehreli said: TypeTuple is great because it enables compile-time foreach (unfortunately, implicitly): foreach (m; __traits(allMembers, A)) { // This body is repeated for each member at compile time } Is there a way I can build an ENUM from within the FOREACH? What I want to achive is, that I would like to use: final switch (myEnum) ... Sorry, I don't understand your question. :( Do you want to define an enum at compile time? Then you can use mixins. Do you want to build an enum value inside the foreach? Yes, it is possible as well. and have myEnum build at compiletime. With this the compiler would give an error whenever I have forgotten to update my code to handle a new case. I need a code example. Sorry. :( 2. I'm wondering why members1 doesn't has a type at all. Because it is a TypeTuple of values of various types and even types themselves. But shouldn't be the type than be TypeTuple? A TypeTuple can contain types and values, which can be checked at compile time: import std.stdio; import std.typetuple; // A function template void foo(T...)() { foreach (i, a; T) { static if (is (a)) { writefln(Argument %s is a type: %s, i, a.stringof); } else { writefln(Argument %s is not : %s, i, a.stringof); } } } // Another one: void bar(T, size_t N)() { T[N] arr; } void main() { alias args = TypeTuple!(int, 42); foo!args(); bar!args(); } Ali
Re: CTFE enums static assert
On 2015-05-04 22:22:51 +, ketmar said: as i said, `typeid` is runtime feature, so you can't print it with pragma. and tuples aren't exist in runtime, it's compile-time only. i think you are even more confused now. ;-) sorry. No, that makes it much more clearer for me. The compiler should print it: No type. typeid() is run-time only. And everything would be clear. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
CTFE enums static assert
I find this a bit strange: // get all rules that start with p... enum BolRules = StaticFilter!(beginsWithP, __traits(allMembers,BolSource)); static assert(is(BolRules == enum)); Compiling using dmd... source/app.d(114): Error: static assert (is(BolRules == enum)) is false I'm trying to construct an enum that can be used in a final switch to check if all cases were handled. But so far it's not working, because I can't get the enum constructed. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: CTFE enums static assert
On Mon, 04 May 2015 18:21:59 +0200, Robert M. Münch wrote: I find this a bit strange: // get all rules that start with p... enum BolRules = StaticFilter!(beginsWithP, __traits(allMembers,BolSource)); static assert(is(BolRules == enum)); Compiling using dmd... source/app.d(114): Error: static assert (is(BolRules == enum)) is false I'm trying to construct an enum that can be used in a final switch to check if all cases were handled. But so far it's not working, because I can't get the enum constructed. that's due to `enum` keyword abusing. enum type is something like this: enum MyEnum { A, B } and enum val = false; is a compile-time boolean constant, which will be inlined on using. i.e. compiler will inline such enum constants, and that constants has the corresponding type, they aren't enums. signature.asc Description: PGP signature
Re: CTFE enums static assert
On 2015-05-04 17:21:34 +, ketmar said: that's due to `enum` keyword abusing. enum type is something like this: enum MyEnum { A, B } and enum val = false; is a compile-time boolean constant, which will be inlined on using. i.e. compiler will inline such enum constants, and that constants has the corresponding type, they aren't enums. Hmm... Ok, I understand that these seems to be two different things. Not sure if I now understand this correct then: enum A {a, b, c}; enum members1 = __traits(allMembers, A); auto members2 = __traits(allMembers, A); pragma(msg, typeof(members1)); pragma(msg, typeid(members1)); pragma(msg, typeof(members2)); pragma(msg, typeid(members2)); Gives this: (string, string, string) playground.d(9): Error: no type for typeid(members1) playground.d(9):while evaluating pragma(msg, typeid(members1)) (string, string, string) playground.d(12): Error: no type for typeid(members2) playground.d(12):while evaluating pragma(msg, typeid(members2)) 1. So the (string, string, string) output is based on the expression of members1? Meaning, the right-hand-side. 2. I'm wondering why members1 doesn't has a type at all. So, we don't have a compile-time boolean? 3. For members2, where auto is used, I would expect that the return type of allMembers is used. Which would be a tuple. But again, no type for members2. Which I find quite strange. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: CTFE enums static assert
On 05/04/2015 11:07 AM, Robert M. Münch wrote: enum A {a, b, c}; enum members1 = __traits(allMembers, A); auto members2 = __traits(allMembers, A); 1. So the (string, string, string) output is based on the expression of members1? Meaning, the right-hand-side. There are many different kinds of tuples in D, only two of which I can handle: 1) Tuple from std.typecons, which are ordinarily created at run time 2) TypeTuple from std.typetuple, which are compile-time entities The documentation is not clear that __traits(allMembers) returns a TypeTuple, which additionally has a bad name. TypeTuple is great because it enables compile-time foreach (unfortunately, implicitly): foreach (m; __traits(allMembers, A)) { // This body is repeated for each member at compile time } It is also possible to expand members of a TypeTuple just by putting it inside an array: [ __traits(allMembers, A) ]On 05/04/2015 11:07 AM, Robert M. Münch wrote: enum A {a, b, c}; enum members1 = __traits(allMembers, A); auto members2 = __traits(allMembers, A); 1. So the (string, string, string) output is based on the expression of members1? Meaning, the right-hand-side. There are many differents kinds of tuples in D, only two of which I can handle: 1) Tuple from std.typecons, which are ordinarily created at run time 2) TypeTuple from std.typetuple, which are compile-time entities The documentation is not clear that __traits(allMembers) returns a TypeTuple, which additionally has a bad name. TypeTuple is great because it enables compile-time foreach (unfortunately, implicitly): foreach (m; __traits(allMembers, A)) { // This body is repeated for each member at compile time } It is also possible to expand members of a TypeTuple just by putting it inside an array: [ __traits(allMembers, A) ] However, it should be obvious that all members must have a common type to be members of the same array. (True to its name, TypeTuple can have types themselves as well.) Powerful stuff. :) 2. I'm wondering why members1 doesn't has a type at all. Because it is a TypeTuple of values of various types and even types themselves. So, we don't have a compile-time boolean? I don't understand that one. :( Ali However, it should be obvious that all members must have a common type to be members of the same array. (True to its name, TypeTuple can have types themselves as well.) Powerful stuff. :) 2. I'm wondering why members1 doesn't has a type at all. Because it is a TypeTuple of values of various types and even types themselves. So, we don't have a compile-time boolean? I don't understand that one. :( Ali
Re: CTFE enums static assert
On Mon, 04 May 2015 20:07:27 +0200, Robert M. Münch wrote: Gives this: (string, string, string) playground.d(9): Error: no type for typeid(members1) playground.d(9):while evaluating pragma(msg, typeid(members1)) `typeid` is runtime thing, you can't use it in compile-time. besides, as Ali said, `allMembers` returns tuple, which is very special thing that exists only in compile-time. 1. So the (string, string, string) output is based on the expression of members1? Meaning, the right-hand-side. that's three field names for `enum A`. and field name is a string. 2. I'm wondering why members1 doesn't has a type at all. So, we don't have a compile-time boolean? it's a tuple. actually, `(string, string, string)` is a special type. 3. For members2, where auto is used, I would expect that the return type of allMembers is used. it is. ;-) Which would be a tuple. But again, no type for members2. Which I find quite strange. as i said, `typeid` is runtime feature, so you can't print it with pragma. and tuples aren't exist in runtime, it's compile-time only. i think you are even more confused now. ;-) sorry. signature.asc Description: PGP signature