Re: CTFE enums static assert

2015-05-18 Thread Robert M. Münch via Digitalmars-d-learn

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

2015-05-15 Thread Robert M. Münch via Digitalmars-d-learn

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

2015-05-15 Thread Ali Çehreli via Digitalmars-d-learn

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

2015-05-05 Thread Robert M. Münch via Digitalmars-d-learn

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

2015-05-04 Thread Robert M. Münch via Digitalmars-d-learn

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

2015-05-04 Thread ketmar via Digitalmars-d-learn
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

2015-05-04 Thread Robert M. Münch via Digitalmars-d-learn

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

2015-05-04 Thread Ali Çehreli via Digitalmars-d-learn

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

2015-05-04 Thread ketmar via Digitalmars-d-learn
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