CTFE and Static If Question

H. S. Teoh hsteoh at quickfur.ath.cx
Thu May 7 15:29:01 UTC 2020


On Thu, May 07, 2020 at 03:00:18PM +0000, jmh530 via Digitalmars-d-learn wrote:
> I am curious how ctfe and static ifs interact.

Then you should find this article helpful:

	https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time


> In particular, if an enum bool passed as a template parameter or
> run-time one will turn an if statement into something like a static if
> statement (perhaps after the compiler optimizes other code away). In
> the code below, I am a function that takes a bool as a template
> parameter and another that has it as a run-time parameter. In the
> first, I just pass an compile-time bool (y0) into it. In the second I
> have run-time (x0) and compile-time (y0).

There are multiple things here that should not be confused:

1) Template instantiation (includes static if): a template takes some
   number of compile-time arguments, and emits multiple copies of the
   template definition, with said arguments substituted for its
   parameters. Templates are processed early on in the compilation
   process, and can change the structure of the AST that the compiler
   sees.

2) CTFE: runs code that has already been compiled into a form that's
   ready to be emitted as runtime code, and feeds the return value back
   to the compiler so that it can be used as a compile-time value
   somewhere else.  Note that CTFE can only run code that has *passed*
   the template instantiation stage (even though the resulting value
   *can* be used for instantiation of other templates, but it cannot
   change the CTFE'd code itself).

3) Code optimization: this takes place independently of (1) and (2), and
   happens as part of code generation. It basically tries to transform
   the machine code so that it runs more efficiently at runtime.  It may
   simplify statements or eliminate redundant / dead code, but this has
   nothing to do with templates, static if, or CTFE; it's a
   transformation applied toward the end of the compilation process and
   it's universally applied to all runtime code (unless you disable
   optimizations).


> Does foo!y0(rt) generate the same code as foo(rt, y0)?

It generates a different AST structure.  But at the end, the optimizer
may reduce them into the same code, depending on the circumstances.


> How is the code generated by foo(rt, x0) different from foo(rt,y0)?

There is no difference, except that in the latter case, the optimizer
may realize that the argument is a compile-time constant, and inline the
function with its return value instead of emitting a runtime call. This
has nothing to do with templates or CTFE, it's purely an optimizer issue
(and different optimizers may do things differently -- it does not
change the meaning of the code).


> auto foo(bool rtct)(int rt) {
>     static if (rtct)
>         return rt + 1;
>     else
>         return rt;
> }
> 
> auto foo(int rt, bool rtct) {
>     if (rtct == true)
> 	    return rt + 1;
>     else
>         return rt;
> }
> 
> void main() {
>     int rt = 3;
>     bool x0 = true;
>     bool x1 = false;
>     assert(foo(rt, x0) == 4);
>     assert(foo(rt, x1) == 3);
> 
>     enum y0 = true;
>     enum y1 = false;
>     assert(foo!y0(rt) == 4);
>     assert(foo!y1(rt) == 3);
>     assert(foo(rt, y0) == 4);
>     assert(foo(rt, y1) == 3);
> }
[...]


T

-- 
IBM = I Blame Microsoft


More information about the Digitalmars-d-learn mailing list