Jonathan M Davis wrote:
> On Friday, September 21, 2012 00:11:51 Jens Mueller wrote:
> > I thought foo is interpreted at compile time.
> > There seems to be a subtle difference I'm not getting.
> > Because you can do the factorial using CTFE even though you have
> > recursion. I.e. there you have a call to the function itself. I.e. it
> > can be compiled because you just insert a call to the function. But for
> > a template you cannot issue something like call for instantiation.
> > Have to think more about it. But your answer helps a lot. Pushes me in
> > the right direction.
>
> Okay. Straight up recursion works. So, with this code
>
> int func(int value)
> {
> if(value < 10)
> return func(value + 1);
> return value;
> }
>
> enum var = func(5);
>
> var would be 10. The problem is that you're trying to pass the result of a
> recursive call as a template argument. As far as a function's behavior goes,
> it's identical regardless of whether it's run at compile time or runtime
> (save
> that __ctfe is true at compile time but not runtime). To quote the docs:
>
> ------
> Any functions that execute at compile time must also be executable at
> run time. The compile time evaluation of a function does the
> equivalent
> of running the function at run time. This means that the semantics of a
> function cannot depend on compile time values of the function. For ex
> ample:
>
> int foo(char[] s) {
> return mixin(s);
> }
>
> const int x = foo("1");
>
> is illegal, because the runtime code for foo() cannot be generated. A
> function template would be the appropriate method to implement this
> sort of thing.
> ------
Is it also illegal to do
int foo(char[] s) {
if (__ctfe)
return mixin(s);
else
return ""; // or assert(false)
}
?
Because this is executable at run time.
> You're doing something very similar to passing a function argument to a mixin
> statement, but in this case, it's passing the result of calling a function
> which doesn't exist yet (since it hasn't been fully compiled) to a template.
>
> In order for your foo function to be called, it must be fully compiled first
> (including its entire body, since CTFE needs the full definition of the
> function, not just its signature). The body cannot be fully compiled until
> the
> template that it's using is instantiated. But that template can't be compiled
> until foo has been compiled, because you're passing a call to foo to it as a
> template argument. So, you have a circular dependency.
I see. That's is clear to me now. Thanks.
> Normal recursion avoids this, because it only depends on the function's
> signature, but what you're doing requires that the function be _run_ as part
> of the process of defining it. That's an unbreakable circular dependency and
> will never work. You need to redesign your code so that you don't require a
> function to call itself while it's being defined. Being called at compile
> time
> is fine, but being called while it's being compiled is not.
But if the function wasn't compiled but interpreted at compile time it
would be possible, wouldn't it?
Jens