2 Templates Issues (possibly bugs)

BCS ao at pathlink.com
Sun Oct 7 16:08:26 PDT 2007


Reply to John,

> Thanks BCS,
> 
> I still have questions below..
> 
> BCS Wrote:
> 
>>> template Template1(T, alias Var, alias Func)
>>> {
>>> T abc = Func();		//OK.
>>> T xyz = Var;		//#1 Error: non-constant expression i1
>>> //Question 1: Why do I have this error?
>>> }
>>> The above error is issued in case I instantiate the template like
>>> this
>>> for ex:
>>> Template1!(int, i1, Func1).abc = 3;
>>> Or
>>> Template1!(int, i1, Func1).xyz = 3;
>> what is i1 in this case.
>> 
> i1 is defined inside main() like this:
> int i1=900;

In that case the problem is that i1 is not a constant expression. A variable 
declared inside of a template in many respects is like a global variable, 
or a static variable in a struct. As such, if you declare it and initialize 
it at the same time then the thing used to initialize it must be a constant. 
In your case i1 isn't.

>> that is correct, referencing the variable var1 but not using it for
>> anything has no effect and is disallowed.
>> 
> What I understand is that "Template2!(int,Func1,Func2).var1;" is
> equivalent to
> int var1 = TFunc1();
> Isn't it? If so, then what's wrong with it?

In D a template is a scope. Everything inside of it is instanced once for 
each set of arguments that the template is used with. As such Template!(int,Func1,Func2).var1 
is just another variable. Ignoring the template stuff for a moment what you 
get is approximately the same as this:

// At the location Template1 is defined
int var1 = TFunk1(); 

...

// At the location Template1 is used.
var1;

If you want to plop down an instance of everything in the template in the 
current scope, then you need to use a mixin.

>> The template you defined contains two global variables that are
>> initialized with the return from two function that are passed in.
>> 
>> The two issues you mention may be related. What I think is happening
>> is that the initializer for a variable must be a constant. Due to
>> compile time function evaluation (CTFE) the trivial function you used
>> get converted to there return values.
>> 
> Yes it seems to be so, but I don't see any restriction in the
> documentation that the initialization must be with a constant.
> 

I could be mistaken, but I think the only case where a con constant finalization 
is allowed is for local variables in a function (this is related to the fact 
that executable code is only allowed in a function). As noted above, the 
declaration inside a template are effectively global and as such are not 
inside a function, thus they need constants if they are initialized.

>> If I had to guess, I'd say that the "i1" from above is a non trivial
>> function that can't be run through CTFE.
>> 
> I tried something: I referenced a global var inside Func2(), and I got
> the error: "Error: cannot evaluate Func2() at compile time", thus
> confirming your thoughts. But as I said, why isn't this allowed, is it
> a template restriction? Where is it stated in the document?

see above.

> 
> Strangely, adding a writefln() call inside Func2() doesn't cause any
> error like this, although this call cannot be done in compile-time!
> 

Unless something else is happening that is a bug. Did it actually compile 
and run with that version? If it gave another error, then it might not have 
gotten that far. Get everything else sorted out and if writefln still works, 
then you have found a bug.

>> as noted above, the expression "Template2!(int,Func1,Func2).var1" is
>> a symbol in all cases. it is actually a reference to a global
>> variable declared in the template.
>> 
> This is not what I understand; what I know is that template definition
> doesn't define any variables, it's same as class definition. No object
> is defined until the class is instantiated.
> 
> A global var would be declared if I instantiate the template or use a
> template mixin.
>

I think I covered this above, but to be sure...

As you note, a template definition doesn't define any variables. However 
when you uses a template (e.i. Template1(Type, Foo, Bar) ) then you have 
defined the set of symbols described inside the template. If you then use 
the template again with different arguments, then you define another set 
of symbols. It is interesting to note that you can declare a template with 
a non const variable in it and then reference the same variable from different 
locations.

template T(char[] name)
{
   int i=0;
}

void main()
{
  T!("hello").i = 5;
  T!("world").i = 7;
  T!("hello").i --;
  T!("world").i ++;

  writef("%d, %d\n", T!("hello").i, T!("world").i); // should print "4, 8"
}

It seems that you are thinking of template just slightly different than D 
uses them. I'm guessing that this is coming from using template in some other 
language (C++ perhaps?) that  has a slightly different take on them.






More information about the Digitalmars-d mailing list