HerpDerpington
HerpDerpington

Reputation: 4473

Is the compiler forced to evaluate if expressions depending on template parameters?

Consider this code snippet:

#include <iostream>

struct A {

    void f() { std::cout << "f"; }
    void g() { std::cout << "g"; }

    template <bool b>
    void call() { (b ? f() : g()); }
};

int main()
{
    A().call<true>();
}

Depending on the template paramter passed to call, either f or g will be called. My question is, if the compiler is somehow forced to pre-evaluate the if condition. Consider this other possible implementation of call:

template <bool b>
void call() { 
    bool x = b;    
    (x ? f() : g()); 
}

In this case, the compile-time template is first converted into a runtime variable, before the decision on f or g is made. I would assume, that the compiler would not be able to remove the if statement in this case.

Indeed, if I test this behaviour with godbolt that seems to be exactly what happens.

Is there some part of the standard that defines which template expressions have to be evaluated at compile-time?

(Of course, in this simple example, I could easily write specializations for b == true and b == false, but that is not what this question is about.)

Upvotes: 1

Views: 87

Answers (1)

Lukas-T
Lukas-T

Reputation: 11350

All template expressions are evaluated at compile time, because templates don't exist at runtime. You can use if constexpr which is garantueed to be evaluated at compile time:

template <bool b>
void call() { if constexpr (b) f(); else g(); }

In you example (for b = true) this will become

void call() { f(); }

regardless of optimization level.

However when you use a normal if or a ternary operator the generated code might be easily optimized. In your example (again for b=true) template instantion creates something like this:

void call() { (true ? f() : g()); }

which the compiler can easily optimize if you allow him to. G++ with -O3 for example just removes the instantion of A and the call to call alltogether and just moves std::cout << "f" into main. See on godbolt.


Concolusion: All template expressions are evaluated at compile time, but the compiler can recognize if an expression or variable is constant and is able to optimize such cases, but the compiler is not obliged to do so (you don't want optimized code when you try to debug something)

Upvotes: 2

Related Questions