nested enum like template generator

JS js.mdnq at gmail.com
Tue Jul 16 16:01:09 PDT 2013


On Tuesday, 16 July 2013 at 21:12:36 UTC, Ali Çehreli wrote:
> On 07/16/2013 02:01 PM, Ali Çehreli wrote:
>
> > On 07/16/2013 01:40 PM, JS wrote:
>
> >  > It would be nice if we had some way to data globally(in
> module).
> >  >
> >  > e.g., __ctfestore["name"] = value;
> >
> > I would expect model-level objects start their lives after
> the program
> > starts running but their initial value can be calculated
> during compile
> > time:
> >
> > import std.stdio;
> > import std.conv;
> >
> > int[string] ctfestore;
> >
> > static this()
> > {
> >      ctfestore = A!().globalFunc();
> > }
>
> Ok, I've been silly. That's not CTFE. I meant something like 
> this:
>
> static this()
> {
>     enum initialValue = A!().globalFunc();
>     ctfestore = initialValue;
> }
>
> And only then I got the problem:
>
> > template A()
> > {
> >      int c;
> >
> >      int[string] globalFunc()
> >      {
> >          int[string] result;
> >
> >          void func()
> >          {
> >              for ( ; c < 10; ++c) {
>
> Error: static variable c cannot be read at compile time
>        called from here: func()
>        called from here: globalFunc()
>
> >                  result[c.to!string] = c;
> >              }
> >          }
> >
> >          func();
> >          return result;
> >      }
> > }
> >
> > void main()
> > {
> >      writeln(ctfestore);
> > }
> >
> > Prints:
> >
> > ["0":0, "4":4, "8":8, "1":1, "5":5, "9":9, "2":2, "6":6,
> "3":3, "7":7]
>
> Ali

yes, that error is the bitch that D loves to slap me with 
constantly when using ctfe's and I have to use wierd methods to 
get around it. Note that I am mainly talking about string mixins 
but the issue is that c is a template variable which is a compile 
time construct that has no real meaning inside a ctfe(if that 
makes sense). This is why nested functions have to be used... but 
then if you want global variables(cross-template variables) you 
need some other technique, if it's even possible.

template A() {
int c;  // doesn't create a variable c for functions in the 
template to use but tells the template define a variable when 
used, I guess, as a normal template(not a mixin).

That is, I was initially thinking `int c;` created a compile time 
variable inside the template but it doesn't... c does't even 
exist until the template is used, but by then, it's too late... 
specially if the template is used as a string mixin.

I think we would need somethign like

template A() {

template int c; // or possibly internal int c;

which defines c as a template variable(not a symbolic expression 
inserted into code where A is used.

here is code that makes it clear:
module main;

import std.stdio, std.cstream, std.conv;

template A()
{
     int c;
     int foo() { return ++c; }
     enum A = foo();  // Comment out to change A to a standard 
template
}


void main(string[] argv)
{	
	alias A!() a;
	//writeln(a.c, a.foo());
	writeln(a);
}

Note that A is used two different ways. A as a sort of function 
itself(with return foo() and, if that line is commented out, as a 
sort of container holding an int and a function.

I think this is the confusion that I had not realizing they are 
two different beasts.

When A is acting as a container, foo can use c no problem. When A 
is acting as a ctfe, foo can't use c. I'm not sure if this is a 
flaw, bug, or what...

I don't see any reason why it can't work both ways, and nesting 
the template as a function works to solve the compile time error.

I think both concepts can be unified by having the compiler 
implicitly wrap everything inside the template in a function, 
accept assignments to A, when used as a ctfe. (this may not work 
well though but a start in the right direction)





More information about the Digitalmars-d-learn mailing list