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